block.json is the metadata file defining a WordPress block. It names the block and describes its behaviour. It can also declare attributes, supports, assets, relationships, styles, variations, and rendering.
WordPress recommends this file as the canonical registration source. PHP, JavaScript, build tools, and WordPress can read one shared contract.
The file does not contain the complete block implementation. Editor components, styles, and rendering code usually live elsewhere. Metadata connects those pieces reliably.
What block.json controls at a glance
Name, title, version, and API version.
Category, icon, description, and keywords.
Attributes, context, supports, and selectors.
Scripts, styles, modules, and rendering.
A minimal block.json example
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "acme/notice",
"version": "1.0.0",
"title": "Notice",
"category": "text",
"icon": "info",
"description": "Displays a short notice.",
"textdomain": "acme",
"attributes": {
"content": { "type": "string", "source": "html", "selector": "p" }
},
"supports": {
"color": true,
"spacing": { "margin": true, "padding": true }
},
"editorScript": "file:./index.js",
"style": "file:./style-index.css"
}
This example creates no editor interface by itself. It describes the registered type and points toward built assets. JavaScript still supplies editing and saving behaviour.
Why WordPress prefers metadata registration
Older blocks often repeated registration settings across PHP and JavaScript. Those copies could drift. One side might declare different attributes, supports, or asset handles.
A shared metadata file reduces that duplication. WordPress can register the server definition from disk. JavaScript can import the same definition during its build.
Server registration also makes the block discoverable through WordPress APIs. The Block Type REST endpoint lists server-registered blocks. Client-only registration cannot provide that server knowledge.
The official metadata reference recommends block.json registration since WordPress 5.8. Treat its current schema as authoritative.
The name is the permanent identity
The name field uses a namespace and slug. An example is acme/notice. That value connects stored comments with registered code.
Choose it carefully. Renaming a block later changes its identity. Existing content still references the earlier name.
Names use lowercase letters, numbers, and dashes. One slash separates the namespace. The namespace prevents collisions between unrelated plugins.
A display title can change without changing stored identity. The name should remain stable. Translate the title, never the registered name.
API version and package version differ
apiVersion selects the Block API behaviour expected by the implementation. It does not describe your plugin release. Use the newest supported version unless compatibility requires otherwise.
The version field describes the block package version. Build systems can use it for asset versions. It can also support cache control.
These values solve different problems. Incrementing the plugin version does not automatically change apiVersion. Test API upgrades before raising that field.
The schema field improves authoring
The optional $schema property points editors toward WordPress metadata rules. Compatible tools can then provide completion, descriptions, and validation.
The trunk schema reflects current development. Version-specific schemas also exist. Choose a schema matching your support policy and validation workflow.
A schema catches spelling mistakes before WordPress silently ignores them. It cannot prove the linked files work. Runtime tests remain necessary.
Titles, descriptions, icons, and keywords
The title appears throughout the editor. Keep it short and recognisable. The description should explain the outcome, not repeat the name.
Keywords improve inserter search. Include genuine synonyms and familiar tasks. Do not stuff every adjacent product term into this field.
The icon can use a Dashicon slug or supported icon definition. Its shape should remain clear at small sizes. Decorative detail disappears quickly.
The category groups the block inside the inserter. Core categories include text, media, design, widgets, theme, and embed. Unknown categories need sensible fallbacks.
Parent, ancestor, and allowedBlocks
Relationship fields shape valid insertion contexts. They do not merely change browsing labels. Each field expresses a different structural rule.
parentrequires a named direct parent block.ancestorpermits the block anywhere below named ancestors.allowedBlockslimits which children a container may receive.
Use these constraints for genuine component relationships. Overly strict rules complicate transforms and migration. Underused rules allow broken combinations.
Test inserter visibility in every expected nesting level. Also test copy, paste, transforms, and template insertion. Context bugs often hide outside direct insertion.
Attributes describe persistent block data
The attributes object describes values a block reads and saves. Each entry can declare a type, default, source, selector, or allowed values.
Those declarations guide parsing and validation. They do not create controls automatically. The edit component decides how users change each value.
Storage depends on the declared source. Some values live inside saved HTML. Others live inside the block comment delimiter.
Our attribute storage guide maps every supported source. It also explains validation and migration choices.
Supports enable standard capabilities
The supports object opts into standard WordPress features. Examples include colour, spacing, typography, layout, locking, alignment, and renaming.
WordPress can add attributes and controls for supported features. The implementation must still apply generated wrapper properties correctly.
The theme can further limit available settings. Therefore, support does not guarantee unlimited controls. Our Block Supports guide explains that handshake.
Context connects related blocks
A parent can expose selected values through providesContext. Descendants request them through usesContext. This avoids copying every shared setting into every child.
Context suits values tied to the surrounding block tree. It is not a general global state system. Consumers only receive registered context within their ancestry.
Namespace context keys to prevent collisions. Document required providers. A child should handle missing optional context without crashing.
Selectors target support-generated styles
The selectors property can direct generated styles toward suitable inner elements. This helps complex blocks whose wrapper is not the visual target.
For example, typography may belong on a quotation element. Colour may belong on a separate label. Metadata records those mappings centrally.
Selectors depend on stable markup. A class change can break generated styling. Include selector coverage in frontend regression tests.
Script properties have distinct scopes
editorScriptloads JavaScript only inside the editor.scriptloads JavaScript in the editor and frontend.viewScriptloads classic JavaScript only on the frontend.viewScriptModuledeclares a frontend JavaScript module.
Use the narrowest correct scope. Editor-only controls should not reach visitors. Frontend interactions do not always belong inside the editor.
A property can reference a registered handle or local file. Local paths begin with file:. Arrays can combine multiple resources where supported.
Generated asset files may include dependency metadata. WordPress uses that information during registration. Missing build artefacts cause silent or visible failures.
Style properties also have scopes
editorStyleapplies only inside the editor.styleapplies inside the editor and frontend.viewStyletargets only frontend output.
Shared structural styles often belong under style. Editor-only outlines belong under editorStyle. Visitor-only enhancements can use viewStyle.
Exact loading behaviour depends on registration and WordPress configuration. Metadata registration enables optimised asset loading. Measure the final page rather than assuming success.
The render property enables dynamic output
The render property points toward a PHP rendering file. WordPress can use it when no separate callback overrides rendering.
Dynamic output fits changing data or centralised markup. Static output fits durable saved HTML. Metadata can support either architecture.
A dynamic block may still save fallback content. That choice improves deactivation behaviour. It also adds validation and migration responsibilities.
Read our server-side rendering guide before choosing that tradeoff. Rendering location affects caching, editing, and failure modes.
Styles, variations, and block hooks
Metadata can register block styles and variations. Styles change appearance through classes. Variations provide alternate starting configurations or scopes. More on that in block styles vs block variations.
Block hooks can place a block near another block automatically. That behaviour changes document structure. Use it transparently and provide suitable controls.
Large variation definitions can become difficult to maintain inside JSON. Some projects register complex variations with JavaScript. Keep shared truth clear either way.
How server registration works
Plugins commonly call register_block_type() with the built metadata directory. WordPress reads block.json and registers linked assets and settings.
The source directory may contain uncompiled files. Production registration should usually target the build directory. That directory needs the copied metadata and referenced assets.
Registering only in JavaScript limits server awareness. Dynamic rendering then cannot work. API discovery and optimised asset handling also suffer.
Register on both sides through shared metadata. Then extend client behaviour through the JavaScript registration call. Avoid redefining every field manually.
Localisation starts in metadata
The textdomain links translatable metadata with a plugin translation domain. WordPress marks fields like titles and descriptions for localisation.
Names, attribute keys, and technical handles remain stable. User-facing labels can change by language. Translators need clear source phrases without embedded jargon.
Test translated titles inside narrow editor interfaces. Long translations can overflow controls. Metadata correctness does not guarantee readable layouts.
Source files and build files
Many projects keep editable metadata under src. Their build copies it into build. WordPress loads the production copy.
Editing only the built copy creates temporary fixes. The next build overwrites them. Editing only the source copy achieves nothing until rebuilding.
Commit source and required production artefacts according to project policy. Verify package archives contain every referenced file. Local development can hide missing release assets.
Performance benefits need verification
Metadata helps WordPress associate assets with individual blocks. Compatible loading paths can enqueue assets only when those blocks appear.
This can reduce unused frontend code. It does not automatically make large assets small. Shared dependencies and theme behaviour still affect delivery.
Test a page without the block. Then test one instance and many instances. Inspect network requests, transferred bytes, execution, and generated CSS.
Common block.json mistakes
- The registered directory lacks the built metadata file.
- A file path points toward a missing artefact.
- PHP and JavaScript still redefine conflicting attributes.
- The namespace or block name changes after release.
- A source attribute lacks matching saved markup.
- Supports are enabled without wrapper integration.
- User-facing strings lack the correct text domain.
- The API version exceeds the supported WordPress baseline.
- Frontend code is assigned to an unnecessarily broad scope.
- The package omits files present during local development.
Many metadata errors fail quietly. The block might register with defaults. Test expected properties through the editor and REST response.
Migrating an older block to block.json
- Inventory every existing registration property.
- Create metadata with the unchanged registered name.
- Copy attributes and defaults exactly.
- Map scripts and styles to correct scopes.
- Add supports without changing saved behaviour.
- Register the built directory on the server.
- Import shared metadata into client registration.
- Rebuild and inspect the release package.
- Open historical blocks without saving them.
- Test editing, saving, rendering, and deactivation.
Keep the first migration mechanical. New features can follow later. Combining architecture changes with output changes makes failures harder to isolate.
A release checklist for metadata
- Validate JSON against the intended WordPress schema.
- Confirm the name matches historical saved content.
- Check every linked asset exists after building.
- Compare registered attributes across server and client.
- Inspect inserter title, description, icon, category, and keywords.
- Test every parent, ancestor, and child restriction.
- Verify context with and without expected providers.
- Compare editor and frontend wrapper properties.
- Test pages containing no instances.
- Inspect the final distributable archive.
Metadata deserves review like executable code. A one-character change can alter loading or saved data. Require focused tests for every contract change.
Frequently asked questions
Is block.json required for every WordPress block?
No. Older registration methods still exist. WordPress recommends metadata registration for modern blocks and server discovery.
Does block.json contain the block’s React code?
No. It points toward assets and describes behaviour. Editor and saving components live in JavaScript files.
Should WordPress register blocks on the server?
Yes. Server registration enables discovery, dynamic rendering, and improved asset handling through WordPress.
Can block.json load frontend assets conditionally?
It associates assets with blocks. Supported loading paths can avoid enqueueing them on unrelated pages.
Can I rename a block inside block.json?
Changing the title is safe. Changing the registered name breaks identity for previously stored blocks.
The verdict
Good metadata helps third-party blocks behave like WordPress blocks. It cannot rescue weak output or inaccessible controls. Test each free WP Block Suite plugin before buying. Then compare the $299 lifetime suite when several Pro tools fit.

Leave a Reply