Visual Editor - v1.2.0
Starting with v1.2, the artisanpack/related-posts block nests an
artisanpack/post-template as its iteration host — the same hosting
pattern artisanpack/query uses. This change unlocks Query Loop's
WYSIWYG canvas (one editable iteration plus N read-only ghosts),
per-post variants (artisanpack/post-variant), variable grid spans,
and masonry packing for related-posts rails without any per-block
fork.
Saved-content backward compatibility
Pre-#601 Related Posts saves have a flat inner-blocks tree — the
post-title / post-date / post-excerpt children sit directly
under artisanpack/related-posts with no artisanpack/post-template
wrapper.
The QueryInliner::expandRelatedPosts() pre-pass auto-detects this on
the public-render path:
- With a nested
post-template(new content): iterations are expanded under the post-template wrapper, exactly like Query Loop — variants, grid spans, and masonry packing all inherit. - Flat inner blocks (legacy content): the legacy per-iteration
expansion kicks in, producing one
core/post-template-itemper resolved post directly underartisanpack/related-posts. Public render output is unchanged from pre-#601.
No content migration is required. Authors who want to opt into the new capabilities re-save the block (which rewrites the saved tree through the editor template) or insert a new Related Posts block.
Editor changes
- Related Posts no longer exposes layout (list / grid / masonry) or
column controls itself — the nested
artisanpack/post-templateowns those via its existing toolbar + inspector, matching the Query Loop experience. Selecting the inner Post Template surfaces the layout toolbar and column count. - Related Posts gains a Post Variants inspector panel — the same
PostVariantsPanelQuery Loop uses — so authors can register position / pattern / meta variants without leaving the parent block. - The Related Posts inspector keeps the query-level controls: number of posts, offset, and order.
- Newly-inserted Related Posts blocks seed an
artisanpack/post-templatewith the same defaultpost-title/post-date/post-excerptchildren. Existing flat saves are not migrated by the editor on load — they keep rendering through the legacy path. - When no host post is in editor scope (e.g. a template-editor view with no preview post selected), the canvas surfaces an info Notice instead of issuing a preview fetch.
- When the host post matches zero related posts, the canvas keeps the
editable iteration template and surfaces a warning Notice. This
replaces the pre-#601
ap-related-posts__preview-emptytext fallback.
Resolver API change
POST /visual-editor/api/query/resolve accepts a new relatedTo
field — an integer host-post id. When present:
- The server loads the host post via the bound
QueryResolverContract. - It derives the host's primary taxonomy and term ids via
HostRelatedTermsResolver::hostRelatedTerms()(categories → tags → generictermsfallback, mirroringQueryInliner::expandRelatedPosts). - The payload is rewritten into a
taxQuery: { taxonomy, terms, operator: 'IN' }related-by-taxonomy query withexclude: [hostId], then forwarded to the resolver. relatedTois mutually exclusive withtaxQueryat the request layer.
When the host post can't be loaded or carries no related-terms signal, the controller short-circuits with an empty paginator envelope (no resolver call for the related query).
Renderer parity
The related-posts wrapper now emits only the ap-related-posts class
across all three renderers (Blade / React / Vue). Layout (grid /
masonry / list) and column count are rendered by the nested
artisanpack/post-template via its existing is-layout-* / columns-N
classes — the same module the standalone Query Loop renders against,
so masonry + grid-spans + variants reuse one CSS module instead of
forking per host.
The pre-#601 wrapper classes (ap-related-posts-has-N-columns,
ap-related-posts__item*, etc.) and their styles have been removed —
they only existed for the legacy flat-card preview UX that is no
longer wired up.
Out of scope (intentional)
- Pagination siblings (
artisanpack/query-pagination*) — Related Posts is a finite list capped atnumPosts: 10; pagination has no conceptual meaning. artisanpack/query-titleandartisanpack/query-no-resultssiblings.- Inline editing of individual non-first iterations (variants are the per-post override mechanism, same as Query Loop).
- Changing the "relatedness" rule. Related Posts stays locked to "same post type, sharing at least one term in the host's primary taxonomy".
- The
enhancedPaginationattribute onrelated-posts/block.jsonis preserved for saved-content safety but remains unsurfaced in the editor.