Block Type Metadata Edit

To register a new block type using metadata that can be shared between codebase that uses JavaScript and PHP, start by creating a block.json file. This file:

  • Gives a name to the block type.
  • Defines some important metadata about the registered block type (title, category, icon, description, keywords).
  • Defines the attributes of the block type.
  • Registers all the scripts and styles for your block type.

Example:

{
    "apiVersion": 2,
    "name": "my-plugin/notice",
    "title": "Notice",
    "category": "text",
    "parent": [ "core/group" ],
    "icon": "star",
    "description": "Shows warning, error or success notices…",
    "keywords": [ "alert", "message" ],
    "textdomain": "my-plugin",
    "attributes": {
        "message": {
            "type": "string",
            "source": "html",
            "selector": ".message"
        }
    },
    "providesContext": {
        "my-plugin/message": "message"
    },
    "usesContext": [ "groupId" ],
    "supports": {
        "align": true
    },
    "styles": [
        { "name": "default", "label": "Default", "isDefault": true },
        { "name": "other", "label": "Other" }
    ],
    "example": {
        "attributes": {
            "message": "This is a notice!"
        }
    },
    "editorScript": "file:./build/index.js",
    "script": "file:./build/script.js",
    "editorStyle": "file:./build/index.css",
    "style": "file:./build/style.css"
}

The same file is also used when submitting block to Block Directory.

Server-side registration Server-side registration

There is also register_block_type_from_metadata function that aims to simplify the block type registration on the server from metadata stored in the block.json file.

This function takes two params:

  • $path (string) – path to the folder where the block.json file is located or full path to the metadata file if named differently.
  • $args (array) – an optional array of block type arguments. Default value: []. Any arguments may be defined. However, the one described below is supported by default:
    • $render_callback (callable) – callback used to render blocks of this block type.

It returns the registered block type (WP_Block_Type) on success or false on failure.

Example:

register_block_type_from_metadata(
    __DIR__ . '/notice',
    array(
        'render_callback' => 'render_block_core_notice',
    )
);

Top ↑

Block API Block API

This section describes all the properties that can be added to the block.json file to define the behavior and metadata of block types.

Name Name

  • Type: string
  • Required
  • Localized: No
  • Property: name
{ "name": "core/heading" }

The name for a block is a unique string that identifies a block. Names have to be structured as namespace/block-name, where namespace is the name of your plugin or theme.

Note: A block name can only contain lowercase alphanumeric characters, dashes, and at most one forward slash to designate the plugin-unique namespace prefix. It must begin with a letter.

Note: This name is used on the comment delimiters as <!-- wp:my-plugin/book -->. Block types in the core namespace do not include a namespace when serialized.

Top ↑

Title Title

  • Type: string
  • Required
  • Localized: Yes
  • Property: title
{ "title": "Heading" }

This is the display title for your block, which can be translated with our translation functions. The block inserter will show this name.

Top ↑

Category Category

  • Type: string
  • Required
  • Localized: No
  • Property: category
{ "category": "text" }

Blocks are grouped into categories to help users browse and discover them.

The core provided categories are:

  • text
  • media
  • design
  • widgets
  • theme
  • embed

Plugins and Themes can also register custom block categories.

An implementation should expect and tolerate unknown categories, providing some reasonable fallback behavior (e.g. a “text” category).

Top ↑

Parent Parent

  • Type: string[]
  • Optional
  • Localized: No
  • Property: parent
{ "parent": [ "my-block/product" ] }

Setting parent lets a block require that it is only available when nested within the specified blocks. For example, you might want to allow an ‘Add to Cart’ block to only be available within a ‘Product’ block.

Top ↑

Icon Icon

  • Type: string
  • Optional
  • Localized: No
  • Property: icon
{ "icon": "smile" }

An icon property should be specified to make it easier to identify a block. These can be any of WordPress’ Dashicons (slug serving also as a fallback in non-js contexts).

Note: It’s also possible to override this property on the client-side with the source of the SVG element. In addition, this property can be defined with JavaScript as an object containing background and foreground colors. This colors will appear with the icon when they are applicable e.g.: in the inserter. Custom SVG icons are automatically wrapped in the wp.primitives.SVG component to add accessibility attributes (aria-hidden, role, and focusable).

Top ↑

Description Description

  • Type: string
  • Optional
  • Localized: Yes
  • Property: description
{
    "description": "Introduce new sections and organize content to help visitors"
}

This is a short description for your block, which can be translated with our translation functions. This will be shown in the block inspector.

Top ↑

Keywords Keywords

  • Type: string[]
  • Optional
  • Localized: Yes
  • Property: keywords
  • Default: []
{ "keywords": [ "keyword1", "keyword2" ] }

Sometimes a block could have aliases that help users discover it while searching. For example, an image block could also want to be discovered by photo. You can do so by providing an array of unlimited terms (which are translated).

Top ↑

Text Domain Text Domain

  • Type: string
  • Optional
  • Localized: No
  • Property: textdomain
{ "textdomain": "my-plugin" }

The gettext text domain of the plugin/block. More information can be found in the Text Domain section of the How to Internationalize your Plugin page.

Top ↑

Attributes Attributes

  • Type: object
  • Optional
  • Localized: No
  • Property: attributes
  • Default: {}
{
    "attributes": {
        "cover": {
            "type": "string",
            "source": "attribute",
            "selector": "img",
            "attribute": "src"
        },
        "author": {
            "type": "string",
            "source": "html",
            "selector": ".book-author"
        }
    }
}

Attributes provide the structured data needs of a block. They can exist in different forms when they are serialized, but they are declared together under a common interface.

See the the attributes documentation for more details.

Top ↑

Provides Context Provides Context

  • Type: object
  • Optional
  • Localized: No
  • Property: providesContext
  • Default: {}

Context provided for available access by descendants of blocks of this type, in the form of an object which maps a context name to one of the block’s own attribute.

See the block context documentation for more details.

{
    "providesContext": {
        "my-plugin/recordId": "recordId"
    }
}

Top ↑

Context Context

  • Type: string[]
  • Optional
  • Localized: No
  • Property: usesContext
  • Default: []

Array of the names of context values to inherit from an ancestor provider.

See the block context documentation for more details.

{
    "usesContext": [ "message" ]
}

Top ↑

Supports Supports

  • Type: object
  • Optional
  • Localized: No
  • Property: supports
  • Default: {}

It contains as set of options to control features used in the editor. See the the supports documentation for more details.

Top ↑

Block Styles Block Styles

  • Type: array
  • Optional
  • Localized: Yes (label only)
  • Property: styles
  • Default: []
{
    "styles": [
        { "name": "default", "label": "Default", "isDefault": true },
        { "name": "other", "label": "Other" }
    ]
}

Block styles can be used to provide alternative styles to block. It works by adding a class name to the block’s wrapper. Using CSS, a theme developer can target the class name for the block style if it is selected.

Plugins and Themes can also register custom block style for existing blocks.

Top ↑

Example Example

  • Type: object
  • Optional
  • Localized: No
  • Property: example
{
    "example": {
        "attributes": {
            "message": "This is a notice!"
        }
    }
}

It provides structured example data for the block. This data is used to construct a preview for the block to be shown in the Inspector Help Panel when the user mouses over the block.

See the the example documentation for more details.

Top ↑

Editor Script Editor Script

  • Type: string (WPDefinedAsset)
  • Optional
  • Localized: No
  • Property: editorScript
{ "editorScript": "file:./build/index.js" }

Block type editor script definition. It will only be enqueued in the context of the editor.

Top ↑

Script Script

  • Type: string (WPDefinedAsset)
  • Optional
  • Localized: No
  • Property: script
{ "script": "file:./build/script.js" }

Block type frontend script definition. It will be enqueued both in the editor and when viewing the content on the front of the site.

Top ↑

Editor Style Editor Style

  • Type: string (WPDefinedAsset)
  • Optional
  • Localized: No
  • Property: editorStyle
{ "editorStyle": "file:./build/index.css" }

Block type editor style definition. It will only be enqueued in the context of the editor.

Top ↑

Style Style

  • Type: string (WPDefinedAsset)
  • Optional
  • Localized: No
  • Property: style
{ "style": "file:./build/style.css" }

Block type frontend style definition. It will be enqueued both in the editor and when viewing the content on the front of the site.

Top ↑

Assets Assets

Top ↑

WPDefinedAsset WPDefinedAsset

The WPDefinedAsset type is a subtype of string, where the value represents a path to a JavaScript or CSS file relative to where block.json file is located. The path provided must be prefixed with file:. This approach is based on how npm handles local paths for packages.

An alternative would be a script or style handle name referencing a registered asset using WordPress helpers.

Example:

In block.json:

{
    "editorScript": "file:./build/index.js",
    "editorStyle": "my-editor-style-handle"
}

In the context of WordPress, when a block is registered with PHP, it will automatically register all scripts and styles that are found in the block.json file and use file paths rather than asset handles.

That’s why, the WPDefinedAsset type has to offer a way to mirror also the shape of params necessary to register scripts and styles using wp_register_script and wp_register_style, and then assign these as handles associated with your block using the script, style, editor_script, and editor_style block type registration settings.

It’s possible to provide an object which takes the following shape:

  • handle (string) – the name of the script. If omitted, it will be auto-generated.
  • dependencies (string[]) – an array of registered script handles this script depends on. Default value: [].
  • version (string|false|null) – string specifying the script version number, if it has one, which is added to the URL as a query string for cache busting purposes. If the version is set to false, a version number is automatically added equal to current installed WordPress version. If set to null, no version is added. Default value: false.

The definition is stored inside separate PHP file which ends with .asset.php and is located next to the JS/CSS file listed in block.json. WordPress will automatically detect this file through pattern matching. This option is the preferred one as it is expected it will become an option to auto-generate those asset files with @wordpress/scripts package.

Example:

build/
├─ index.js
└─ index.asset.php

In block.json:

{ "editorScript": "file:./build/index.js" }

In build/index.asset.php:

<?php
return array(
    'dependencies' => array(
        'wp-blocks',
        'wp-element',
        'wp-i18n',
    ),
    'version'      => '3be55b05081a63d8f9d0ecb466c42cfd',
);

Top ↑

Internationalization Internationalization

WordPress string discovery automatically will translate fields marked in the documentation as translatable using the textdomain property when specified in the block.json file. In that case, localized properties will be automatically wrapped in _x function calls on the backend of WordPress when executing register_block_type_from_metadata. These translations are added as an inline script to the wp-block-library script handle in WordPress core or to the plugin’s script handle.

Example:

{
    "title": "My block",
    "description": "My block is fantastic",
    "keywords": [ "fantastic" ],
    "textdomain": "my-plugin"
}

The way register_block_type_from_metadata processes translatable values is roughly equivalent to:

<?php
$metadata = array(
    'title'       => _x( 'My block', 'block title', 'my-plugin' ),
    'description' => _x( 'My block is fantastic!', 'block description', 'my-plugin' ),
    'keywords'    => array( _x( 'fantastic', 'block keywords', 'my-plugin' ) ),
);

Implementation follows the existing get_plugin_data function which parses the plugin contents to retrieve the plugin’s metadata, and it applies translations dynamically.

Top ↑

Backward Compatibility Backward Compatibility

The existing registration mechanism (both server side and frontend) will continue to work, it will serve as low-level implementation detail for the block.json based registration.

Once all details are ready, Core Blocks will be migrated iteratively and third-party blocks will see warnings appearing in the console to encourage them to refactor the block registration API used.

The following properties are going to be supported for backward compatibility reasons on the client-side only. Some of them might be replaced with alternative APIs in the future:

  • edit – see the Edit and Save documentation for more details.
  • save – see the Edit and Save documentation for more details.
  • transforms – see the Transforms documentation for more details.
  • deprecated – see the Deprecated Blocks documentation for more details.
  • merge – undocumented as of today. Its role is to handle merging multiple blocks into one.
  • getEditWrapperProps – undocumented as well. Its role is to inject additional props to the block edit’s component wrapper.

Example:

wp.blocks.registerBlockType( 'my-block/name', {
    edit: function () {
        // Edit definition goes here.
    },
    save: function () {
        // Save definition goes here.
    },
    getEditWrapperProps: function () {
        // Implementation goes here.
    },
} );

In the case of dynamic blocks supported by WordPress, it should be still possible to register render_callback property using both register_block_type and register_block_type_from_metadata functions on the server.