Kid playing with some LEGO blocks

The WordPress block editor is changing everything related to how we create content with this platform. There are many novelties that the new releases of WordPress bring regarding blocks, and there is still a long way to go in the future.

For this reason, developers who work with WordPress as a development platform should feel increasingly comfortable working with blocks. However, making the leap from PHP to JavaScript-based technologies can be tough.

Anyway, you have to update your skills and not be afraid of the new WordPress development stack. The sooner we are comfortable with it, the more opportunities we will have to innovate.

Working with blocks from outside of WordPress can be frustrating if you don't know how.
Working with blocks from outside of WordPress can be frustrating if you don’t know how to do it.

Today we are going to see how we can work with Gutenberg blocks without having to be inside the WordPress editor. Why? For several reasons…

The first and most obvious is because we can. For some time now, the definition of the core blocks in the Gutenberg editor has been available as a separate code package. This means that we can use them outside of WordPress thanks to the NPM package manager.

In addition, there is a whole series of functions to manage blocks and work with them. And they are also contained in their own package. Therefore, if we want to work with the standard WordPress blocks, we only have to import these two packages as dependencies in our project.

To achieve this, we must create a folder for our project, run npm init to create a package.json file with the project data, and then run the following command to install these two dependencies:

npm install @wordpress/block-library @wordpress/blocks

The next step is to create an index.js file with the code we want to execute. This code is written in Node.js, a variant of JavaScript that runs on servers. For today’s example, the content of index.js can be as follows:

const { 
} = require( '@wordpress/block-library' );
const { 
} = require( '@wordpress/blocks' );
const myBlock = createBlock( 
  content: 'This is a block created programmatically',
const serializedBlock = serialize( myBlock );
console.log( serializedBlock );

The first two statements that appear in the preceding code are require statements to import the dependencies. As I said before, we want to import the standard WordPress block definition. We do this with require('@wordpress/block-library'). Since we only want to import the registerCoreBlocks function from this package, on the left side of the equality symbol we destructure that function.

In the same way we import the @wordpress/blocks package as a dependency. This package is the one that has the functions to work with blocks. There are a lot of functions defined in the package (you have them here), but for this example we only want createBlock to create new blocks and serialize to convert them into strings that we can save in the content of a WordPress post.

Now that we have the dependencies imported, we call the registerCoreBlocks function, which loads the definition of the standard WordPress block types so we can use them. From then on we can create blocks, as you can see when we call the createBlock function passing as a parameter the name of the type of block we want to create and an object with its attributes.

In the previous example we are going to create a paragraph block, so we pass the name 'core/paragraph' and inside the attributes object we pass the content of the paragraph to be created as a string inside the content key.

Finally, we call the serialize function, passing it the block we just created. As a result we will have a string that we can output with the console.log function.

Now we can run the above code typing node index.js in the terminal. If we do that, the following happens:

Failing output after running the Node.js code to work with blocks.
Failing output after running the Node.js code to work with blocks.

There is an error in the execution! The reason is that we need to have the window variable available, which is not defined. But what is this variable and why do we need it?

Window is a JavaScript object that the browser defines and represents the browser window itself. Since we are executing the code in our terminal (or if it were running in production, on a server), we do not have a browser with said variable. Does this mean we can’t use WordPress blocks outside a browser? Of course it doesn’t!

Node.js has several packages that allow us to simulate that we are running our code in a browser environment. In this case, we are going to use the browser-env package. We just have to install it as we did before with the WordPress packages:

npm install browser-env

In our index.js file we have to add a new require to import the browser-env dependency. But also, we have to “fix” the window object since it does not come with the required matchMedia method. If you copy the following code and add it to the beginning of the index.js file, the problem is solved:

// Setup environment to simulate a browser
// (mandatory to register Gutenberg blocks).
require( 'browser-env' )();
window.matchMedia =
 window.matchMedia ||
  function () {
   return {
    matches: false,
    addListener: function () {},
    removeListener: function () {},

Now you can run the code again and you will see that it does not fail and that it returns the textual representation of the paragraph block we just created using the createBlock function:

$ node index.js                                             
<!-- wp:paragraph -->
<p>This is a block created programmatically</p>
<!-- /wp:paragraph -->

You have all the code in this GitHub repository. The possibilities for working with blocks from outside the editor are enormous. You can create blocks, clone them, transform them to a different type of block, and much more.

Being able to work with blocks outside the WordPress editor allows us to manipulate the contents of our WordPress and work with them from anywhere. This opens up a world of enormous possibilities for developers that we are just beginning to explore.

We at Nelio are already making use of these possibilities. We’ll soon launch a new service that you’ll hopefully find very interesting. Stay tuned for the news that we are going to release in the upcoming weeks ?.

Featured image by Kelly Sikkema on Unsplash.

5 responses to “How to work with WordPress blocks outside Gutenberg with Node.js”

  1. Marie Avatar

    Thanks you a lot, that’s what I was looking for !

  2. Guy Leblond Avatar
    Guy Leblond

    Hello, I am following your instructions, but I am getting this error:

    throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);

    Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\xampp7421\htdocs\andk\wp\node_modules\rememo\rememo.js
    require() of ES modules is not supported.
    require() of C:\xampp7421\htdocs\andk\wp\node_modules\rememo\rememo.js from C:\xampp7421\htdocs\andk\wp\node_modules\@wordpress\blocks\build\store\selectors.js is an ES module file as it is a .js file whose nearest parent package.json contains “type”: “module” which defines all .js files in that package scope as ES modules.
    Instead rename rememo.js to end in .cjs, change the requiring code to use import(), or remove “type”: “module” from C:\xampp7421\htdocs\andk\wp\node_modules\rememo\package.json.

    I tried different node versions (18.3.0, 14.19.3, 13.14.0, 12.12.12..) as well as applying some fixes found on internet, without success. Could you tell me what different package version you are using ? THanks

    1. Antonio Villegas Avatar

      I tried the GitHub project right now using node v14.15.0 and everything worked just fine.

  3. Terrence Avatar

    Thank you sir! Very helpful, saved me some time on finding the proper configuration
    I think it doesn’t work on the newest versions of it all, but the configuration from GH repo is all good

Leave a Reply

Your email address will not be published. Required fields are marked *

I have read and agree to the Nelio Software Privacy Policy

Your personal data will be located on SiteGround and will be treated by Nelio Software with the sole purpose of publishing this comment here. The legitimation is carried out through your express consent. Contact us to access, rectify, limit, or delete your data.