block.json Generator

Generate a block.json for a Gutenberg block: name, attributes, supports, asset file references and the API version the block editor expects.

Live output

Enable JavaScript to customise; default output below.

Your plugin or theme. It keeps your block apart from every other block called card.

Stored in the post content as a comment, so renaming it later invalidates every existing block.

What the inserter shows.

A dashicon name with the prefix dropped, such as index-card.

Search keywords

Extra words the inserter search matches. The title is already searched.

More options Show

Used to bust the browser cache for this block's assets.

Live preview block.json
{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "my-plugin/card",
	"version": "1.0.0",
	"title": "Card",
	"category": "design",
	"icon": "index-card",
	"description": "A titled box with an image and a link.",
	"keywords": [
		"card",
		"box"
	],
	"attributes": {
		"heading": {
			"type": "string",
			"default": ""
		},
		"showImage": {
			"type": "boolean",
			"default": true
		}
	},
	"supports": {
		"html": false,
		"anchor": true,
		"align": [
			"wide",
			"full"
		],
		"color": {
			"background": true,
			"text": true,
			"link": false
		},
		"spacing": {
			"padding": true,
			"margin": false
		},
		"typography": {
			"fontSize": true,
			"lineHeight": false
		}
	},
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css",
	"render": "file:./render.php",
	"textdomain": "my-plugin"
}

Output is valid and updates as you type.

Describe the block and copy out a block.json that the editor, register_block_type() and wp-scripts all read from the same file.

How to use

  1. Namespace the block with your plugin or theme slug. The full name is stored in post content, so it has to be unique and it has to stay the same.
  2. Declare every attribute you plan to save. Anything not listed is discarded when the post is saved, which is the usual cause of “my setting does not stick”.
  3. Choose dynamic rendering when the output depends on anything outside the post: a query, an option, the current user. Static is for markup that never changes after saving.
  4. Turn supports on deliberately. Every one you enable is another control in the sidebar and another set of classes in the markup.
  5. Put the file in your block’s folder and point register_block_type() at that folder, not at the file.

Example

A dynamic block with two attributes:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "acme/card",
	"title": "Card",
	"category": "design",
	"attributes": {
		"heading": {
			"type": "string",
			"default": ""
		}
	},
	"editorScript": "file:./index.js",
	"render": "file:./render.php",
	"textdomain": "acme"
}

apiVersion 3 is what puts the block editor’s canvas in an iframe. A block written for version 1 or 2 that assumes it shares a document with the editor breaks there.

Pitfalls

  • The block name is written into every post that uses the block. Renaming it turns existing content into an invalid block warning.
  • An attribute that is not declared is not saved. The editor keeps it in memory until the page reloads, which makes the bug look intermittent.
  • file: paths are relative to the block folder and are resolved by register_block_type(). An absolute URL there is not handled.
  • apiVersion 3 renders the editor canvas in an iframe. Code that reaches for document or for a global stylesheet stops working.
  • align with wide or full does nothing unless the theme supports those alignments.
  • A dynamic block ignores the saved markup entirely, so a save function that returns anything but null fights the PHP render.
  • viewScriptModule needs WordPress 6.5. On older versions use viewScript.
  • Attribute defaults are not applied to blocks that already exist in content. Old blocks come back with the attribute missing, not with the default.

Compatibility

block.json metadata has been read by register_block_type() since WordPress 5.8, apiVersion 3 needs WordPress 6.3, and viewScriptModule needs 6.5. The $schema line is for your editor’s autocomplete and is ignored by WordPress. The tool runs entirely in your browser.

Frequently asked questions

Do I need apiVersion 3?
Use it for anything new on WordPress 6.3 or later. It is the iframed canvas, which is where the editor is going.
Why is my attribute not saved?
It is not declared in attributes. Undeclared values are dropped on save.
Dynamic or static rendering?
Dynamic when the output depends on anything outside the post. Static when the markup is fixed once the editor has finished with it.
Where do the file: paths point?
At the built files in the block folder, the ones wp-scripts build writes. Point register_block_type() at the folder holding this file.
Can I add my own metadata?
Yes, unknown top level keys are ignored by WordPress and readable through WP_Block_Type_Registry. Namespace them so they do not collide later.

From the people who built this tool

WP Adminify

The WordPress admin, rebuilt: a dashboard worth looking at, menu and column control, a real file manager and the login page your client sees.

See WP Adminify Free version on WordPress.org

Weekly drops

New tools, when there are new tools

One email when something worth using ships. No schedule to fill, so no filler.

Your address goes nowhere else, and one click unsubscribes.