Block registration makes your block available in the WordPress Block Editor. You register blocks using the registerBlockType function from the @wordpress/blocks package.
registerBlockType Function
Either a block name string (namespace/block-name) or a block.json metadata object
Block configuration object containing edit, save, and other properties
Returns
The registered block type object, or undefined if registration fails
Registration Methods
Method 1: JavaScript-Only Registration
import { registerBlockType } from '@wordpress/blocks' ;
import { __ } from '@wordpress/i18n' ;
registerBlockType ( 'my-plugin/book' , {
title: __ ( 'Book' ),
category: 'widgets' ,
icon: 'book-alt' ,
description: __ ( 'Block showing a Book card.' ),
keywords: [ __ ( 'reading' ), __ ( 'library' ) ],
attributes: {
title: {
type: 'string' ,
source: 'html' ,
selector: 'h3' ,
},
author: {
type: 'string' ,
source: 'html' ,
selector: '.book-author' ,
},
pages: {
type: 'number' ,
},
},
edit : ( { attributes , setAttributes } ) => {
return (
< div >
< h3 > { attributes . title } </ h3 >
< p > { attributes . author } </ p >
</ div >
);
},
save : ( { attributes } ) => {
return (
< div >
< h3 > { attributes . title } </ h3 >
< div className = "book-author" > { attributes . author } </ div >
</ div >
);
},
} );
Method 2: Using block.json (Recommended)
The recommended method uses a block.json metadata file:
block.json
{
"$schema" : "https://schemas.wp.org/trunk/block.json" ,
"apiVersion" : 3 ,
"name" : "core/button" ,
"title" : "Button" ,
"category" : "design" ,
"parent" : [ "core/buttons" ],
"description" : "Prompt visitors to take action with a button-style link." ,
"keywords" : [ "link" ],
"textdomain" : "default" ,
"attributes" : {
"text" : {
"type" : "rich-text" ,
"source" : "rich-text" ,
"selector" : "a,button" ,
"role" : "content"
},
"url" : {
"type" : "string" ,
"source" : "attribute" ,
"selector" : "a" ,
"attribute" : "href" ,
"role" : "content"
},
"linkTarget" : {
"type" : "string" ,
"source" : "attribute" ,
"selector" : "a" ,
"attribute" : "target" ,
"role" : "content"
}
},
"supports" : {
"anchor" : true ,
"color" : {
"gradients" : true ,
"__experimentalDefaultControls" : {
"background" : true ,
"text" : true
}
},
"typography" : {
"fontSize" : true ,
"lineHeight" : true
}
},
"styles" : [
{ "name" : "fill" , "label" : "Fill" , "isDefault" : true },
{ "name" : "outline" , "label" : "Outline" }
]
}
index.js
import { registerBlockType } from '@wordpress/blocks' ;
import { button as icon } from '@wordpress/icons' ;
import metadata from './block.json' ;
import edit from './edit' ;
import save from './save' ;
registerBlockType ( metadata , {
icon ,
edit ,
save ,
} );
edit.js
import { useBlockProps , RichText } from '@wordpress/block-editor' ;
export default function Edit ( { attributes , setAttributes } ) {
const blockProps = useBlockProps ();
return (
< div { ... blockProps } >
< RichText
tagName = "a"
value = { attributes . text }
onChange = { ( text ) => setAttributes ( { text } ) }
placeholder = "Add text..."
/>
</ div >
);
}
save.js
import { useBlockProps , RichText } from '@wordpress/block-editor' ;
export default function save ( { attributes } ) {
const blockProps = useBlockProps . save ();
return (
< div { ... blockProps } >
< a href = { attributes . url } target = { attributes . linkTarget } >
< RichText.Content value = { attributes . text } />
</ a >
</ div >
);
}
Block Configuration Properties
Core Properties
Display title shown in the inserter. Should be translated with __() function.
Block category. Core categories: text, media, design, widgets, theme, embed
icon
string | element | object
Icon for the block. Can be a Dashicon slug, SVG element, or icon descriptor object. // Dashicon slug
icon : 'book-alt'
// SVG element
icon : < svg viewBox = "0 0 24 24" >< path d = "M19 13H5v-2h14v2z" /></ svg >
// Icon descriptor
icon : {
background : '#7e70af' ,
foreground : '#fff' ,
src : < svg viewBox = "0 0 24 24" >< path d = "M19 13H5v-2h14v2z" /></ svg > ,
}
Short description shown in the block inspector description : __ ( 'Block showing a Book card.' )
Search terms to help users find the block keywords : [ __ ( 'image' ), __ ( 'photo' ), __ ( 'pics' ) ]
Attributes
Block Hierarchy
Restrict block to only be available when nested within specified parent blocks {
"parent" : [ "core/buttons" ]
}
Block available anywhere within specified ancestor blocks (not just direct children) {
"ancestor" : [ "core/columns" ]
}
Restrict which block types can be nested as direct children {
"allowedBlocks" : [ "core/column" ]
}
Styles and Variations
Alternative visual styles for the block styles : [
{ name: 'default' , label: __ ( 'Rounded' ), isDefault: true },
{ name: 'outline' , label: __ ( 'Outline' ) },
{ name: 'squared' , label: __ ( 'Squared' ) }
]
Block Example
Provides structured data for block preview in inspector and styles panel example : {
attributes : {
content : __ ( 'In a village of La Mancha...' ),
},
}
Real-World Example: Paragraph Block
Here’s how the core Paragraph block is registered:
block.json
{
"apiVersion" : 3 ,
"name" : "core/paragraph" ,
"title" : "Paragraph" ,
"category" : "text" ,
"description" : "Start with the basic building block of all narrative." ,
"keywords" : [ "text" ],
"attributes" : {
"content" : {
"type" : "rich-text" ,
"source" : "rich-text" ,
"selector" : "p" ,
"role" : "content"
},
"dropCap" : {
"type" : "boolean" ,
"default" : false
},
"direction" : {
"type" : "string" ,
"enum" : [ "ltr" , "rtl" ]
}
},
"supports" : {
"anchor" : true ,
"color" : {
"gradients" : true ,
"link" : true
},
"spacing" : {
"margin" : true ,
"padding" : true
},
"typography" : {
"fontSize" : true ,
"lineHeight" : true
}
}
}
index.js
import { paragraph as icon } from '@wordpress/icons' ;
import metadata from './block.json' ;
import edit from './edit' ;
import save from './save' ;
import transforms from './transforms' ;
import deprecated from './deprecated' ;
export const settings = {
icon ,
example: {
attributes: {
content: __ (
'In a village of La Mancha, the name of which I have no desire to call to mind...'
),
},
},
transforms ,
deprecated ,
merge ( attributes , attributesToMerge ) {
return {
content:
( attributes . content || '' ) +
( attributesToMerge . content || '' ),
};
},
edit ,
save ,
};
Block Collections
Group related blocks together in the inserter:
import { registerBlockCollection } from '@wordpress/blocks' ;
registerBlockCollection ( 'my-plugin' , {
title: __ ( 'Custom Collection' ),
icon: 'admin-plugins' ,
} );
// All blocks with 'my-plugin' namespace will appear in this collection
registerBlockType ( 'my-plugin/block-one' , { /* ... */ } );
registerBlockType ( 'my-plugin/block-two' , { /* ... */ } );
Unregistering Blocks
Remove previously registered blocks:
import { unregisterBlockType } from '@wordpress/blocks' ;
unregisterBlockType ( 'core/verse' );
Unregistering core blocks may break existing content. Only unregister blocks if you’re certain they’re not being used.
Server-Side Registration
Register blocks in PHP for better performance:
function my_plugin_register_blocks () {
register_block_type ( __DIR__ . '/build/blocks/book' );
}
add_action ( 'init' , 'my_plugin_register_blocks' );
This automatically reads block.json and registers the block on both server and client.
Validation and Error Handling
The registerBlockType function validates your block configuration:
Invalid name format
Already registered
Valid registration
// ❌ Will show warning and return undefined
registerBlockType ( 'MyBlock' , {} );
// Warning: Block names must contain a namespace prefix
TypeScript Type Definition
interface WPBlockType {
name : string ;
title : string ;
description ?: string ;
category ?: string ;
icon ?: WPBlockTypeIcon ;
keywords ?: string [];
attributes ?: Record < string , any >;
save ?: Component ;
edit : Component ;
variations ?: WPBlockVariation [];
example ?: object ;
}
function registerBlockType (
blockNameOrMetadata : string | object ,
settings : object
) : WPBlockType | undefined ;
Next Steps
Define Block Attributes Learn how to structure your block’s data
Use Block Supports Enable editor features automatically