BlockBridge WP
WordPress plugin that serializes Gutenberg blocks into a structured JSON tree
Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/iwritec0de/blockbridge-wp/archive/refs/heads/main.zipWordPress 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.
How It Works
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: "..." } },
...
]
Installation
- 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 --activate
Usage
Install and activate the plugin, then fetch any post or page from the REST API:
curl https://your-site.com/wp-json/wp/v2/posts/1
The 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 Hooks
blockbridge_ignore_list
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;
} );
blockbridge_block
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 );
blockbridge_block_{blockName}
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;
} );
Supported Block Types
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 |
Development
Install dependencies
composer install
Run tests
composer test
Tests use PHPUnit 9 with Brain\Monkey for WordPress function mocking. No WordPress installation or database is required.
Lint
composer lint