You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This supersedes #1764 (a 2021 "server registry spec" conversation-starter). Since then the landscape has changed substantially: WordPress core now registers blocks server-side via register_block_type + block.json with a block-types REST endpoint for introspection, several ecosystem plugins have shipped different answers for getting block data into GraphQL, and WordPress 6.9/7.0's AI work has added new server-side primitives. There's renewed potential to leverage a server-side block registry to map blocks to GraphQL types.
This is a large, high-impact, and genuinely unsettled design space, so the goal here is not to commit to a solution but to define the problem(s), assess the current state of Gutenberg, and recommend a direction (likely a follow-on RFC, and possibly a new featured plugin rather than core).
First job: identify the problem(s)
Block support means different things to different people, and we should not design until we've named what we're solving. Two broad consumer camps to weigh:
Rendered delivery — fetch the rendered block markup (and/or the React/server-rendered output) and drop it in.
Structured delivery — fetch each block's structured attributes and innerBlocks and map them to the consumer's own components, which may be React, Swift, Svelte, or anything else. The premise: wp-admin authors with React blocks; headless apps query blocks and their data and render them however they like.
Both are valid; the spike should assess demand for each rather than assume.
Current landscape / prior art
Four notably different approaches already exist, worth studying for what works and what doesn't:
Core's stance to date: expose raw post content and leave block parsing to these plugins.
A candidate model (starting point, not a decision)
The wp-graphql-content-blocks overall shape is appealing as a baseline to pressure-test: each Block Type maps to a GraphQL Type, blocks share common interface(s), and each field that can be input/saved on a block is queryable on the block (with innerBlocks handled recursively). A server-side block registry could drive this mapping automatically.
Bigger possibilities to investigate (deliberately ambitious)
Registry-driven type mapping: auto-generate GraphQL types from the server-side block registry + block.json attribute schemas.
Block input mutations: now that we have formal oneOf input support, investigate block inputs for mutations.
Per-block-instance identity: if we can store/derive a stable unique ID per block instance, a node ID could look like post:123:block:<blockId>, enabling querying an individual block via node( id: ... ) and an updateBlock() mutation to mutate a single block rather than the whole post. (If we can solve individual block mutations, individual block subscriptions fall out of the same identity work, but that only becomes relevant if and when WPGraphQL has a formal subscription solution, so it's out of scope for this spike beyond noting it here.) Hard problem: blocks aren't stored as discrete records, they're serialized inside post_content, so stable identity and granular writes are non-trivial.
Delivery vehicle: a new featured plugin (in the model of WPGraphQL for ACF and WPGraphQL Smart Cache) vs core. Leaning toward a featured plugin given the surface area and the upstream churn risk.
WordPress 7.0 server-side tailwind (validate)
WordPress has long lacked good server-side block support, a gap I raised repeatedly over the years (see the historical through-line below). WP 6.9/7.0's AI investment moved things forward: PHP-only block and pattern registration, the Abilities API (server-side in 6.9, JS in 7.0) backing the AI Client and Connectors, and expanded Block Bindings / Pattern Overrides. AI consumers fundamentally need to understand what blocks exist and what inputs they accept, so this is the most aligned upstream momentum we've ever had.
But the WordPress 7.0 Field Guide does not document a formal, REST-introspectable block-type/attribute schema for external consumers, so the foundation may be necessary-but-not-sufficient. Validating exactly what the Abilities API and PHP block registration expose, and whether block.jsonattributes are introspectable server-side / via REST, is a primary task of this spike, and determines how much WPGraphQL must pioneer versus map.
Historical through-line
I've been making this case publicly since 2017:
Gutenberg#2751 (Sept 2017): I argued a comprehensive server-side block registry should be the source of truth for block capabilities, attributes, and their types, the way register_post_type and taxonomies are, so REST, WPGraphQL, alternative editors/page builders, headless apps, and alternate storage (ElasticSearch mappings, future wp_blocks tables) can all read one definition. The WPGraphQL vision I sketched there is today's candidate model: each block a typed GraphQL node (HeadingBlock), context-aware block queries (contentBlocks(where: { context: MOBILE })), __typename per block. The blocker I named then still holds: WPGraphQL can't expose a block's attributes or their enum options unless they're declared server-side.
graphql-js#207 (Dec 2017): I argued GraphQL needed input unions so blocks could be mutated, not just queried (query is easy with unions since each saved block has a concrete type; mutation needs the client to pass __typename + structured input). That input-union ask is essentially what shipped as oneOf, which is why this spike's block-mutation investigation is newly viable.
Open questions to answer in the spike
Gutenberg / block state across interfaces: how complete is PHP-side block registration now (block.json attribute schemas, block bindings, synced/reusable patterns, interactivity API)? Critically, how can blocks be read and written outside the Gutenberg JS editor, via the WP REST API, WP-CLI, and other interfaces? Blocks are serialized in post_content and reusable blocks are a wp_block CPT, but is there first-class block read/write in REST beyond that? And what does the WP 7.0 Abilities API actually expose about blocks and their inputs, is any of it REST-introspectable today? Strong REST/CLI/abilities support signals a clear path for GraphQL integration; little beyond reusable blocks means there's more for WPGraphQL to pioneer, at higher cost and risk.
Identity & storage: can we derive or persist a stable per-instance block ID without fighting post_content serialization? What breaks on re-save/reorder?
Mutations: oneOf block inputs, granular updateBlock vs whole-post writes, validation/sanitization, conflict handling.
Rendered vs structured delivery: do we expose rendered markup, structured attributes, or both, and how?
Core vs featured plugin: where does this live, and what (if anything) belongs in core to enable it?
Custom Scalars / Types: what new scalars or object/interface types would WPGraphQL need to model blocks well (e.g. for block attributes, color/spacing/typography presets, media, rich text)?
Why this spike
This supersedes #1764 (a 2021 "server registry spec" conversation-starter). Since then the landscape has changed substantially: WordPress core now registers blocks server-side via
register_block_type+block.jsonwith a block-types REST endpoint for introspection, several ecosystem plugins have shipped different answers for getting block data into GraphQL, and WordPress 6.9/7.0's AI work has added new server-side primitives. There's renewed potential to leverage a server-side block registry to map blocks to GraphQL types.This is a large, high-impact, and genuinely unsettled design space, so the goal here is not to commit to a solution but to define the problem(s), assess the current state of Gutenberg, and recommend a direction (likely a follow-on RFC, and possibly a new featured plugin rather than core).
First job: identify the problem(s)
Block support means different things to different people, and we should not design until we've named what we're solving. Two broad consumer camps to weigh:
Both are valid; the spike should assess demand for each rather than assume.
Current landscape / prior art
Four notably different approaches already exist, worth studying for what works and what doesn't:
Core's stance to date: expose raw post content and leave block parsing to these plugins.
A candidate model (starting point, not a decision)
The wp-graphql-content-blocks overall shape is appealing as a baseline to pressure-test: each Block Type maps to a GraphQL Type, blocks share common interface(s), and each field that can be input/saved on a block is queryable on the block (with innerBlocks handled recursively). A server-side block registry could drive this mapping automatically.
Bigger possibilities to investigate (deliberately ambitious)
block.jsonattribute schemas.oneOfinput support, investigate block inputs for mutations.post:123:block:<blockId>, enabling querying an individual block vianode( id: ... )and anupdateBlock()mutation to mutate a single block rather than the whole post. (If we can solve individual block mutations, individual block subscriptions fall out of the same identity work, but that only becomes relevant if and when WPGraphQL has a formal subscription solution, so it's out of scope for this spike beyond noting it here.) Hard problem: blocks aren't stored as discrete records, they're serialized insidepost_content, so stable identity and granular writes are non-trivial.WordPress 7.0 server-side tailwind (validate)
WordPress has long lacked good server-side block support, a gap I raised repeatedly over the years (see the historical through-line below). WP 6.9/7.0's AI investment moved things forward: PHP-only block and pattern registration, the Abilities API (server-side in 6.9, JS in 7.0) backing the AI Client and Connectors, and expanded Block Bindings / Pattern Overrides. AI consumers fundamentally need to understand what blocks exist and what inputs they accept, so this is the most aligned upstream momentum we've ever had.
But the WordPress 7.0 Field Guide does not document a formal, REST-introspectable block-type/attribute schema for external consumers, so the foundation may be necessary-but-not-sufficient. Validating exactly what the Abilities API and PHP block registration expose, and whether
block.jsonattributesare introspectable server-side / via REST, is a primary task of this spike, and determines how much WPGraphQL must pioneer versus map.Historical through-line
I've been making this case publicly since 2017:
register_post_typeand taxonomies are, so REST, WPGraphQL, alternative editors/page builders, headless apps, and alternate storage (ElasticSearch mappings, futurewp_blockstables) can all read one definition. The WPGraphQL vision I sketched there is today's candidate model: each block a typed GraphQL node (HeadingBlock), context-aware block queries (contentBlocks(where: { context: MOBILE })),__typenameper block. The blocker I named then still holds: WPGraphQL can't expose a block's attributes or their enum options unless they're declared server-side.__typename+ structured input). That input-union ask is essentially what shipped asoneOf, which is why this spike's block-mutation investigation is newly viable.Open questions to answer in the spike
block.jsonattribute schemas, block bindings, synced/reusable patterns, interactivity API)? Critically, how can blocks be read and written outside the Gutenberg JS editor, via the WP REST API, WP-CLI, and other interfaces? Blocks are serialized inpost_contentand reusable blocks are awp_blockCPT, but is there first-class block read/write in REST beyond that? And what does the WP 7.0 Abilities API actually expose about blocks and their inputs, is any of it REST-introspectable today? Strong REST/CLI/abilities support signals a clear path for GraphQL integration; little beyond reusable blocks means there's more for WPGraphQL to pioneer, at higher cost and risk.post_contentserialization? What breaks on re-save/reorder?oneOfblock inputs, granularupdateBlockvs whole-post writes, validation/sanitization, conflict handling.register_block_typewith GraphQL args (ashow_in_graphql-style opt-in + type mapping) the same way post types, taxonomies, settings, and meta are handled? This spike's registry-driven mapping is a sibling of 🎯 Tracking: mapping WordPress data registries (settings, meta, options) to the WPGraphQL Schema #3931's settings/meta/options mapping.Deliverables
Out of scope (for now)
Committing WPGraphQL core to block support. That decision is an output of this spike, not an input.