Overview
In this recipe, you’ll get hands-on with the Block Transforms API, learning how to control block conversions like a pro. You’ll see how to convert your custom block into others, transform existing blocks into yours, and even insert your block via text—making content editing more seamless than ever. Let’s dive in and start experimenting! 🔄👨🍳
Setup
You can choose to either use the repository which provides a development environment or to just download the standalone plugin
Standalone
Instructions
Run the following command in a terminal of your choice from inside the plugins directory of your local WordPress installation.
npx @wordpress/create-block@latest transforms --template @block-developer-cookbook/transformsOnce the scaffold has completed completed, start the build process from inside the newly created plugin
cd transforms && npm run startFinally, make sure to activate the plugin.
Repository
Instructions
Checkout the repository (skip this step if already done)
git clone git@github.com:ryanwelcher/block-developer-cookbook.gitInstall the dependencies
npm installStart the development environment (make sure you have Docker installed)
npm run env startRun the following script from the root of the repository
npm run prep:transformsOnce the scaffold has completed completed, start the build process from inside the newly created plugin
cd plugins/transforms && npm run startStep 1 – The block your building
You will be adding custom transforms for a provided custom block called Transformer.
The block is very simple, it displays the Autobots logo and has single attribute called message. Feel free to look at the source code for the block to get a better understanding of how it is built.
In order to register transforms for a block, they must be added to the registerBlockType call for the block via the transforms property.
If you open ./src/index.js, you will see the following at the bottom of the file:
registerBlockType( metadata.name, {
edit: Edit,
transforms: transformers,
icon: Autobots,
} );The transforms property is being assigned the value of the transformers object which is being imported from the ./src/transforms.js file and will contain all of the transforms for this block.
Step 2 – Adding your first transform
Open the ./src/transforms.js and have a look at the transformers object.
const transformers = {
to: [],
from: [],
};
export default transformers;Transforms type objects are stored in sub keys that represent the transformation direction. A block can be transformed to something or from something.
Once you’ve decided the direction, there six types of transforms that can be chosen from. However, the only type that supports both the to and from direction is the block type.
blockenterfilesprefixrawshortcode
Let’s add a transformation from this block to the core/paragraph block using the block type.
Define a new transform object in the to array with the following:
const transformers = {
to: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes, innerBlocks ) => {},
},
],
from: [],
};
export default transformers;The blocks property is the list of blocks that this block can transform into. This list is shown in the block toolbar.

The transform property is a function that is used to make the conversion from one block to another. It receives the attributes and innerBlocks from the block being transformed from.
Inside the transform function, we will need to dynamically create a new block. You will need to use the createBlock function for that so import that and add the following to complete the transform function:
/**
* WordPress dependencies
*/
import { createBlock } from '@wordpress/blocks';
const transformers = {
to: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes, innerBlocks ) => {
return createBlock( 'core/paragraph', {
content: attributes.message,
} );
},,
},
],
from: [],
};
export default transformers;This line is creating a new core/paragraph block and mapping the message attribute from your block to the content attribute in the Paragraph block.
Save your files and test this out! You should be able convert this block into a paragraph block.
Step 3 – Going both ways
Now, create a new transition to go FROM a paragraph block TO your custom block.
The process is basically the same, except you add the transform to the from array and change the block being created in the transforms function.
/**
* WordPress dependencies
*/
import { createBlock } from '@wordpress/blocks';
const transformers = {
to: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes, innerBlocks ) => {
return createBlock( 'core/paragraph', {
content: attributes.message,
} );
},,
},
],
from: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes, innerBlocks ) => {
return createBlock( 'block-developers-cookbook/transforms', {
message: attributes.content,
} );
},
},
],
};
export default transformers;Step 4 – Using text to insert the block
You can use the enter type to have insert your custom block while typing in the the block editor.
This transform type is only support for the from direction and requires a regular expression to capture the text.
Add the following transform object to the from array:
/**
* WordPress dependencies
*/
import { createBlock } from '@wordpress/blocks';
const transformers = {
to: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes, innerBlocks ) => {
return createBlock( 'core/paragraph', {
content: attributes.message,
} );
},,
},
],
from: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes, innerBlocks ) => {
return createBlock( 'block-developers-cookbook/transforms', {
message: attributes.content,
} );
},
},
{
type: 'enter',
regExp: /^rollout!$/,
transform: () => {
return createBlock( 'block-developers-cookbook/transforms' );
},
},
],
};
export default transformers;This code will allow you to type rollout! and press enter to insert your custom block.
Step 5 – Using a prefix to insert your block
You can use the prefix type to have your block inserted by inserted a prefix followed by a space.
Add the following to the from array:
/**
* WordPress dependencies
*/
import { createBlock } from '@wordpress/blocks';
const transformers = {
to: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes, innerBlocks ) => {
return createBlock( 'core/paragraph', {
content: attributes.message,
} );
},,
},
],
from: [
{
type: 'block',
blocks: [ 'core/paragraph' ],
transform: ( attributes, innerBlocks ) => {
return createBlock( 'block-developers-cookbook/transforms', {
message: attributes.content,
} );
},
},
{
type: 'enter',
regExp: /^rollout!$/,
transform: () => {
return createBlock( 'block-developers-cookbook/transforms' );
},
},
{
type: 'prefix',
prefix: '?',
transform: () => {
return createBlock( 'block-developers-cookbook/transforms' );
},
},
],
};
export default transformers;Test this code by adding a ? and pressing the space bar.
Next Steps
Now that you’ve done the prep, you can add this ingredient to your chef’s kit! Try creating a new transforms that will convert your custom block to a Cover block and back!
Hint: You will need to use the innerBlocks parameter and add more default attributes.
See Solution
const transformers = {
to: [
{
type: 'block',
blocks: [ 'core/cover' ],
transform: ( { message }, innerBlocks ) => {
const newInnerBlocks = [
...innerBlocks,
createBlock( 'core/paragraph', {
align: 'center',
content: message,
fontSize: 'large',
placeholder: 'Write title…',
} ),
];
return createBlock(
'core/cover',
{
customOverlayColor: '#be0b24',
},
newInnerBlocks
);
},
},
],
from: [
{
type: 'block',
blocks: [ 'core/cover' ],
transform: ( attributes, innerBlocks ) => {
const [ firstBlock ] = innerBlocks;
const { content } =
firstBlock.attributes || 'More that meets the eye!';
return createBlock( 'block-developers-cookbook/transforms', {
message: content,
} );
},
},
],
};
export default transformers;