Block API v2 Essentials: Metadata, React Edits, and SSR
Master the Block API v2 by defining block.json metadata, implementing React-based edit functions, and leveraging server-side rendering for your plugin.
Previously in this course, we explored State Management with @wordpress/data: Building Scalable Stores and established a robust React Component Architecture: Scaling WordPress Plugin UIs. This lesson pivots to the Block API v2, where we transition from managing application state to rendering that state within the Gutenberg editor.
At this level, "blocks" are no longer just static HTML snippets; they are sophisticated components defined by metadata, managed by React in the editor, and rendered dynamically on the front end.
Defining the block.json Metadata
The block.json file is the source of truth for your block. It replaces the legacy register_block_type PHP arguments, allowing for better performance through selective asset loading.
For our Knowledge Base plugin, we need a block that displays a specific article summary. Here is a production-ready block.json structure:
JSON{ "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 2, "name": "kb-plugin/article-summary", "title": "Knowledge Base Article Summary", "category": "widgets", "attributes": { "articleId": { "type": "integer" } }, "editorScript": "file:./index.js", "render": "file:./render.php" }
By defining render, we tell WordPress that this block is dynamic. Instead of using a save() function to serialize HTML to the database, WordPress will execute the PHP file provided whenever the block is rendered on the front end.
Implementing React Edit Functions
The edit function in your index.js acts as the React entry point for the editor UI. Because we are building a Knowledge Base, we often need to fetch data. We use the useSelect hook to pull data from our custom stores, as discussed in our lesson on State Management with @wordpress/data.
JAVASCRIPTimport { useSelect } from CE9178">'@wordpress/data'; import { useBlockProps } from CE9178">'@wordpress/block-editor'; export default function Edit({ attributes, setAttributes }) { const { articleId } = attributes; // Fetch article details from our custom store const article = useSelect((select) => { return select(CE9178">'kb-plugin/store').getArticle(articleId); }, [articleId]); const blockProps = useBlockProps(); return ( <div {...blockProps}> {article ? ( <h3>{article.title}</h3> ) : ( <p>Select an article to display...</p> )} </div> ); }
Leveraging Server-Side Rendering (SSR)
When you use render_callback or the render property in block.json, you decouple the editor UI from the front-end output. This is vital for a Knowledge Base plugin, as article content might change in the database. If you saved the HTML statically, you would have to update every post whenever an article title changed.
In render.php, you have access to the block's attributes:
PHP<?php #6A9955">// render.php $article_id = $attributes['articleId'] ?? 0; if (!$article_id) { return; } $article = KB_Repository::find($article_id); ?> <div <?php echo get_block_wrapper_attributes(); ?>> <h2><?php echo esc_html($article->title); ?></h2> <div class="kb-content"> <?php echo apply_filters('the_content', $article->content); ?> </div> </div>
Hands-on Exercise
- Create a new block directory in your plugin.
- Define a
block.jsonwithapiVersion: 2. - In your
edit.js, implement a simpleTextControlthat updates thearticleIdattribute. - Implement the
render.phpfile to fetch an article from your database based on thatarticleId. - Verify that changing the ID in the editor immediately updates the preview (if you implemented a preview state) and the front-end output.
Common Pitfalls
- Forgetting
apiVersion: 2: Without this, you lose access touseBlockPropsand the modern wrapper API, forcing you to manually manageclassandidattributes. - Mixing Logic: Avoid putting complex business logic in
render.php. Use your Repository classes (as we covered in our Data Access Objects Pattern lesson) to keep the template clean. - Asset Enqueueing: When using
block.json, assets are registered automatically. Do not manually enqueue them infunctions.phpunless you have a specific reason; otherwise, you risk double-loading scripts.
Recap
We have transitioned to the Block API v2, utilizing block.json for metadata, React for the editor experience, and PHP for dynamic rendering. This architecture ensures your Knowledge Base plugin remains performant and data-consistent.
Up next: We will explore InnerBlocks to create complex, nested Knowledge Base layouts.
Work with me

Custom WordPress Plugin Development
Custom WordPress & WooCommerce plugins built to standard โ by the developer behind a plugin with 5,000+ active installs and a SaaS with 10,000+ users.

Headless WordPress + Next.js Frontend Development
Keep WordPress for content, get a lightning-fast Next.js frontend. The best of both worlds โ familiar editing, modern speed.