Working with ACF

Wonderpress treats Advanced Custom Fields as an optional hydration source for partials. Field definitions live in partial manifests; wonderpress-core registers the ACF groups at runtime; your page templates read the values through wonder_partial_props(). If ACF is absent, core no-ops.

Installing ACF

wonderpress init does not install ACF. When you need it:

code
ACF_PRO_LICENSE=... wonderpress acf install

That downloads and activates ACF directly from its official distribution. PRO is the default because Wonderpress repeater fields require it. The license key is read only from the environment: it is never accepted as a CLI flag, written to the project, or passed to WP-CLI.

Use --free to install the latest free edition from advancedcustomfields.com (that edition has no Repeater). Add --force to reinstall an edition that is already present.

Installing activates the plugin without persisting the PRO license for updates. Put define( 'ACF_PRO_LICENSE', '…' ); in wp-config.php, or activate under ACF → Updates.

Marking a partial ACF-compatible

code
wonderpress partial create --name Testimonials --acf \  --prop items:repeater --sub items:quote:string:required

--acf records acf_compatible: true on the manifest. Core reads manifests on acf/init and registers a field group from the declared properties. Property types string, boolean, email, select, post_object, image, link, and repeater become ACF fields. Optional label, when (conditionals keyed by sibling property name), and whitelisted acf overrides (ui, return_format, wrapper, and similar) are supported.

Repeaters are one level deep, via --sub or nested properties in a --json spec. Flexible content is not generated.

Location: groups appear only where you put them

Partial manifests declare fields only, never ACF location rules. A group with no location is skipped. Without that rule, a Hero metabox and a Hero block would appear on the same screen.

Locate a partial’s group in either of two ways:

  1. Template composition (preferred). List the partial in a page-template manifest’s composition. Core derives the page-template location from that file and registers one combined field group for the template.
  2. The wonderpress_template_fields filter, an explicit PHP map for when you are not using composition:
code
add_filter( 'wonderpress_template_fields', function () {	return array(		'template-landing.php' => array( 'hero', 'testimonials' ),	);} );

Avoid the default key unless you want those partials on every page that uses WordPress’s default template.

Hydrating in the template

code
( new \Wonderpress\Partials\Hero( wonder_partial_props( 'hero' ) ) )->render();

wonder_partial_props( 'hero' ) returns array( 'acf' => get_field( 'hero' ) ); the partial’s construction copies the field values onto flat properties, so the view reads $title and $photo the same as it would from block attributes. With template composition, pass the instance id as the second argument: wonder_partial_props( 'landing-hero', 'hero-main' ).

That landing page typically locks 'all'. On a blog post you insert the Hero block instead, and the field group stays off that screen.

Dual partials

--acf and --block combine: the block authors through Gutenberg attributes, the PHP caller hydrates from ACF, and both paths must deliver the same value shapes to the view. The CLI enforces that every property type on a dual partial is dual-authorable, including transitively through partial embeds. The type tiers and wire formats are in Property types.

The placement rule from above applies with extra force: do not locate the ACF group on a page that also inserts the block.

A property of type: "link" maps to a simple four-field group (content, url, open_in_new_tab, title). To embed the rich Link primitive (type switch, internal, file, email, and telephone targets) inside another partial, reference it as a partial embed:

code
{  "name": "cta",  "type": "partial",  "partial": "link",  "label": "Call to action"}

The fields come from core’s manifest/partials/link.json, which core loads automatically for ACF registration when the partial is located. Render with wonder_render_partial_ref( 'link', $this->cta ) or new \Wonderpress_Core\Partials\Link( [ 'acf' => $this->cta ] ). The standalone manifest is also installable with wonderpress partial install-manifest link.

After editing manifests

Field definitions live in .wonderpress/manifest/partials/*.json. After editing one, run wonderpress partial sync <Name> so the class $_properties and block.json stay aligned, then reload the editor and re-save any page whose groups changed shape.