WordPress plugin that serializes Gutenberg blocks into a structured JSON tree, exposed via the REST API. Pairs with blockbridge-react to render WordPress content as React components in headless applications.
BlockBridge WP adds a serializedBlocks field to every post type that supports the block editor. When a headless front end fetches a post via the REST API, it receives the block tree alongside the standard post fields — no custom endpoint required.
WordPress REST API /wp-json/wp/v2/posts/{id}
→ serializedBlocks: [
{ name: "core/paragraph", _key: "...", content: "Hello world", attributes: {} },
{ name: "core/image", _key: "...", attributes: { url: "...", alt: "..." } },
...
]
- Download or clone this repo into
wp-content/plugins/blockbridge-wp/ - Activate the plugin in Plugins → Installed Plugins
The plugin is currently distributed via GitHub only. WP CLI:
wp plugin install https://github.com/iwritec0de/blockbridge-wp/archive/refs/heads/main.zip --activateInstall and activate the plugin, then fetch any post or page from the REST API:
curl https://your-site.com/wp-json/wp/v2/posts/1The response will include a serializedBlocks array alongside standard post fields. Pass it to BlockContent from blockbridge-react:
import { BlockContent } from '@iwritec0de/blockbridge-react';
export default function Post({ post }) {
return <BlockContent blocks={post.serializedBlocks} />;
}Filter the list of block names the plugin will skip during serialization.
add_filter( 'blockbridge_ignore_list', function( array $ignored ): array {
$ignored[] = 'core/shortcode';
$ignored[] = 'core/legacy-widget';
return $ignored;
} );Filter any block's schema immediately after it is generated. Runs for every block.
Parameters:
$schema(array) — The generated schema for this block. Shape:{ name, _key, content, attributes, children }.$block(array) — The raw block array fromparse_blocks(). ContainsblockName,attrs,innerHTML,innerBlocks.
add_filter( 'blockbridge_block', function( array $schema, array $block ): array {
// Add a custom attribute to every block.
$schema['attributes']['myCustomField'] = get_post_meta(
get_the_ID(),
'_my_custom_field',
true
);
return $schema;
}, 10, 2 );Filter the schema for a specific block type. The block name is normalized (slashes and hyphens become underscores), so core/image becomes blockbridge_block_core/image.
// Add srcset data to image blocks.
add_filter( 'blockbridge_block_core/image', function( array $schema ): array {
$id = $schema['attributes']['id'] ?? 0;
if ( $id ) {
$schema['attributes']['srcset'] = wp_get_attachment_image_srcset( $id, 'full' );
}
return $schema;
} );// Suppress heading blocks above level 2.
add_filter( 'blockbridge_block_core/heading', function( array $schema ): array {
if ( ( $schema['attributes']['level'] ?? 2 ) === 1 ) {
return []; // Returning empty array removes the block from output.
}
return $schema;
} );The plugin serializes all block types. Built-in types receive structured attribute extraction; any unknown block falls back to passing through its raw innerHTML via the content field.
Built-in structured types:
| Block | Key attributes extracted |
|---|---|
core/paragraph |
content, textColor, backgroundColor, fontSize, align, dropCap |
core/heading |
content, level, textColor, backgroundColor, fontSize, align |
core/image |
url, alt, id, caption, linkDestination, href, sizeSlug, width, height |
core/gallery |
columns, caption, imageCrop, linkTo (children = image blocks) |
core/list |
ordered, reversed, start (children = list-item blocks) |
core/list-item |
content |
core/quote |
citation, align (children = paragraph/heading blocks) |
core/button |
text, url, rel, linkTarget, backgroundColor, textColor, borderRadius, className |
core/buttons |
layout (children = button blocks) |
core/group |
tagName, backgroundColor, textColor, layout |
core/columns |
isStackedOnMobile, verticalAlignment, backgroundColor, textColor |
core/column |
width, backgroundColor, textColor |
core/cover |
url, alt, dimRatio, overlayColor, customOverlayColor, minHeight, align, hasParallax, contentPosition, focalPoint |
core/media-text |
mediaType, mediaUrl, mediaAlt, mediaWidth, isStackedOnMobile, verticalAlignment, imageFill |
core/audio |
src, caption, autoplay, loop, preload |
core/video |
src, caption, controls, autoplay, loop, muted, poster |
core/file |
href, fileName, textLinkHref, showDownloadButton, downloadButtonText |
core/separator |
opacity, backgroundColor, color |
core/spacer |
height |
core/table |
hasFixedLayout, caption, head, body, foot, backgroundColor |
core/embed |
url, providerNameSlug, type, responsive, caption |
composer installcomposer testTests use PHPUnit 9 with Brain\Monkey for WordPress function mocking. No WordPress installation or database is required.
composer lint