block.json Schema Reference
The block.json file is the canonical way to register blocks in WordPress. It defines metadata, assets, and behavior for your block.
File Location
Place block.json in your block’s root directory:
my-plugin/
├── blocks/
│ └── my-block/
│ ├── block.json
│ ├── index.js
│ ├── edit.js
│ ├── save.js
│ └── style.css
Complete Schema
Required Fields
$schema
JSON Schema URL for IDE autocompletion:
{
"$schema": "https://schemas.wp.org/trunk/block.json"
}
Use version-specific schemas:
https://schemas.wp.org/wp/6.5/block.jsonhttps://schemas.wp.org/wp/6.4/block.json
apiVersion
Block API version. Currently 3 is latest:
{
"apiVersion": 3
}
| Version | WordPress | Key Changes |
|---|---|---|
| 1 | 5.0+ | Original API |
| 2 | 5.6+ | useBlockProps, block wrapper handling |
| 3 | 6.3+ | render field, improved selectors support |
name
Unique block identifier in namespace/block-name format:
{
"name": "my-plugin/testimonial"
}
Rules:
- Lowercase alphanumeric with hyphens
- Must include namespace and block name
- Namespace should match your plugin/theme
- Cannot use
core/namespace (reserved)
title
Human-readable block name (translatable):
{
"title": "Testimonial"
}
Recommended Fields
version
Block version for cache busting:
{
"version": "1.0.0"
}
category
Block category in inserter:
{
"category": "widgets"
}
Core categories:
text– Text blocksmedia– Image, video, audiodesign– Layout and design elementswidgets– Dynamic widgetstheme– Theme-specific blocksembed– Embed blocks
Register custom categories:
add_filter( 'block_categories_all', function( $categories ) {
return array_merge(
$categories,
[
[
'slug' => 'my-custom-category',
'title' => __( 'My Custom Category', 'my-plugin' ),
'icon' => 'star-filled',
],
]
);
} );
icon
Block icon (Dashicon or custom SVG):
{
"icon": "star-filled"
}
Using Dashicons (without dashicons- prefix):
{
"icon": "admin-comments"
}
Custom SVG (in JavaScript registration, not block.json):
registerBlockType( 'my-plugin/block', {
icon: {
src: <svg viewBox="0 0 24 24"><path d="M12 2L2 7l10 5 10-5-10-5z"/></svg>,
foreground: '#ff0000',
background: '#ffffff',
},
// ...
} );
description
Block description for inserter tooltip:
{
"description": "Display customer testimonials with photo and quote."
}
keywords
Search terms for block inserter (max 3):
{
"keywords": [ "quote", "review", "feedback" ]
}
textdomain
Text domain for translations:
{
"textdomain": "my-plugin"
}
Block Behavior Fields
parent
Restrict block to specific parent blocks:
{
"parent": [ "core/group", "my-plugin/container" ]
}
The block only appears in inserter when inside specified parents.
ancestor
Restrict block to be nested within ancestor (any depth):
{
"ancestor": [ "core/columns" ]
}
Unlike parent, ancestor allows any nesting depth.
allowedBlocks
Restrict which blocks can be inserted as children:
{
"allowedBlocks": [ "core/paragraph", "core/heading", "core/image" ]
}
Attributes
Define block data storage:
{
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "p"
},
"alignment": {
"type": "string",
"default": "left"
},
"count": {
"type": "number",
"default": 3
}
}
}
See attributes.md for complete documentation.
Supports
Enable/disable block features:
{
"supports": {
"align": true,
"color": {
"background": true,
"text": true
},
"typography": {
"fontSize": true,
"lineHeight": true
}
}
}
See supports.md for complete documentation.
Asset Fields
editorScript
JavaScript for editor only:
{
"editorScript": "file:./index.js"
}
Multiple files:
{
"editorScript": [
"file:./index.js",
"file:./sidebar.js"
]
}
Registered handle:
{
"editorScript": "my-plugin-editor"
}
editorStyle
CSS for editor only:
{
"editorStyle": "file:./editor.css"
}
script
JavaScript for both editor and frontend:
{
"script": "file:./script.js"
}
style
CSS for both editor and frontend:
{
"style": "file:./style.css"
}
viewScript
JavaScript for frontend only (when block is present):
{
"viewScript": "file:./view.js"
}
viewScriptModule
ES Module for frontend (WordPress 6.5+):
{
"viewScriptModule": "file:./view.js"
}
viewStyle
CSS for frontend only (WordPress 6.5+):
{
"viewStyle": "file:./view.css"
}
See scripts-styles.md for detailed comparison.
Rendering
render
PHP template for server rendering (API version 3):
{
"render": "file:./render.php"
}
Available variables in render.php:
$attributes– Block attributes$content– InnerBlocks content$block– WP_Block instance
See dynamic-blocks.md for details.
Block Variations
variations
Define block variations:
{
"variations": [
{
"name": "blue",
"title": "Blue Testimonial",
"attributes": {
"backgroundColor": "blue"
}
}
]
}
See variations.md for complete documentation.
Block Styles
styles
Register visual style variants:
{
"styles": [
{
"name": "default",
"label": "Default",
"isDefault": true
},
{
"name": "outlined",
"label": "Outlined"
}
]
}
See styles.md for complete documentation.
Example Content
example
Preview content for inserter:
{
"example": {
"attributes": {
"content": "This is an example testimonial.",
"author": "Jane Doe"
}
}
}
With nested blocks:
{
"example": {
"attributes": {
"title": "My Block"
},
"innerBlocks": [
{
"name": "core/paragraph",
"attributes": {
"content": "Nested paragraph content."
}
}
]
}
}
Disable preview:
{
"example": {}
}
Block Hooks
blockHooks
Automatically insert block relative to others:
{
"blockHooks": {
"core/post-content": "after",
"core/navigation": "firstChild"
}
}
Positions:
before– Insert before targetafter– Insert after targetfirstChild– Insert as first childlastChild– Insert as last child
See hooks.md for complete documentation.
Selectors
selectors
Custom CSS selectors for block styling:
{
"selectors": {
"root": ".wp-block-my-plugin-testimonial",
"border": ".wp-block-my-plugin-testimonial__border",
"typography": {
"root": ".wp-block-my-plugin-testimonial__text"
}
}
}
Provides Context / Uses Context
providesContext
Expose attributes to descendant blocks:
{
"providesContext": {
"my-plugin/recordId": "recordId"
}
}
usesContext
Consume context from ancestors:
{
"usesContext": [ "postId", "postType", "my-plugin/recordId" ]
}
See context.md for complete documentation.
Complete Example
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "my-plugin/testimonial",
"version": "1.2.0",
"title": "Testimonial",
"category": "widgets",
"icon": "format-quote",
"description": "Display customer testimonials with photo, quote, and attribution.",
"keywords": [ "quote", "review", "customer" ],
"textdomain": "my-plugin",
"attributes": {
"quote": {
"type": "string",
"source": "html",
"selector": "blockquote"
},
"author": {
"type": "string",
"source": "html",
"selector": ".author-name"
},
"imageId": {
"type": "number"
},
"imageUrl": {
"type": "string",
"source": "attribute",
"selector": "img",
"attribute": "src"
}
},
"supports": {
"align": [ "wide", "full" ],
"color": {
"background": true,
"text": true,
"gradients": true
},
"spacing": {
"margin": true,
"padding": true
},
"typography": {
"fontSize": true,
"lineHeight": true
}
},
"styles": [
{
"name": "default",
"label": "Default",
"isDefault": true
},
{
"name": "card",
"label": "Card"
}
],
"example": {
"attributes": {
"quote": "This product changed my life!",
"author": "Happy Customer"
}
},
"editorScript": "file:./index.js",
"editorStyle": "file:./editor.css",
"style": "file:./style.css",
"render": "file:./render.php"
}
PHP Registration
Register the block in PHP:
add_action( 'init', function() {
register_block_type( __DIR__ . '/blocks/testimonial' );
} );
The function reads block.json automatically and registers all defined assets.
Validation
Validate your block.json:
npx @wordpress/scripts check-block-json ./blocks/my-block/block.json
Use IDE schema support for real-time validation.