How to Create a Custom Block With The @wordpress/create-block Build Tool

If you feel lost among all the development setup needed to create a custom block, then this guide is for you.

We’ll look in detail at how the @wordpress/scripts package can be used to simplify Gutenberg block development. We’ll start by looking at the technical implementation of the tool. Afterwards we’ll use it to create and then customize a sample block.

You do not need to have any knowledge of custom block development to get started. The tutorial assumes that you are on MacOS X, but it also works with minor changes on Windows and Linux.

Table of Contents

What Is Create Block?

The WP Create Block package is a project generator. Its focus is on generating a WordPress plugin with all the files needed for a working custom block.

This means that whenever you want to create a block, you do not need to do all of the set up yourself. Instead you run a single command, and all the source files and configuration setup is done for you.

The tool is open source, and is maintained by WordPress project.

How Does Create Block Work?

Create Block is a command line tool. This means that you interact with the tool by entering commands into a Terminal window.

There are only a couple of simple commands you need to know. However if you feel uneasy using the command line, I recommend reading this introduction post.

From a technical standpoint, the @wordpress/create-block package is a collection of JavaScript files. To web developers, this might at first seem surprising, as the JavaScript runs as a command line application.

This is made possible by Node.js, a JavaScript run-time environment that executes JavaScript code outside of a browser. Node, and the surrounding ecosystem, is crucial for modern JavaScript development.

So the @wordpress/create-block package is a specific type of JavaScript application, that relies on tools provided by Node to be installed and executed.

On Overview of Node Tooling

The JavaScript code in Create Block is bundled in packages, using the Node Package Manager, or NPM. These packages are then published to the NPM Registry.

The NPM Registry is an online collection of open-source software JavaScript packages. Developers can download these packages, and use them in their own projects.

To do so, developers can interact with this repository via the npm command line tool. As an example running npm install <package-name> will download the requested package to from the repository to your local machine.

npx is a companion to npm, focussed on command line applications and other executables. It downloads and then executes packages from the NPM Registry.

As Create Block relies on Node and NPM, make sure that you have these applications downloaded and installed on your machine.

Using the Create Block Command

Step 1: Check the tooling setup

First we need to verify whether Node and NPM are installed correctly.

Open a terminal window and type node -v. This will show the installed version of Node. It needs to be higher than version 14. Repeat the same for NPM with npm -v. The requirement here is higher than version 6.14.4.

Now that you are all set, we can start creating a plugin for a custom block.

Step 2: Initiate the create command

Navigate to the wp-content/plugins directory of your local development install. Then run npx @wordpress/create-block.

This will download and run the Create Block package. You’ll be asked to confirm whether you want to proceed.

After you run the @wordpress/create-block command, you will need to confirm that this is the package you want to run.

This downloads all of the necessary code from the NPM repository. You them go right into the setup dialogue.

Step 3: Configuring the block

All the block configuration happens through an interactive dialogue.

Using @wordpress/create-block, custom blocks are configured using an interactive dialogue on the command line.

Use the array keys to navigate between options, and hit Enter to confirm and proceed.

These are the questions that are asked:

  • Is this a static or dynamic block?
  • What is the block slug? This is also the name of the plugin directory that the command creates.
  • What is the block namespace? Make this an unique identifier for your company or project.
  • What is the display title? That’s the name of the block as it is displayed in the block inserter.
  • Optional: what is the description of the block? This text is displayed in the editor when the user has inserted the block.
  • Optional: what is the block icon? Through the command line you can only choose from the Dashicons that are part of WordPress.
  • What is the category for the block? The list only includes the categories that are part of WordPress: Text, Media, Design, Widgets, Theme, and Embed.
  • Do you want to customize the WordPress plugin? This allows you to configure the plugin headers of the block plugin.
    I always choose yes here, so that I can set the Update URI to false. This prevents plugins on WordPress.org from interfering with my plugin.

Step 4: Test the plugin

Now all you have to do is sit back and wait for the command to finish.

For our example block, we chose hello-world as the block slug. You’ll find this directory now in wp-content/plugins.

In the WordPress admin, under Plugins, you’ll see our new plugin:

The Hello World block plugin generated by the Create Block package.

Activate the plugin and, add the block to a post:

The custom Hello World block in the block editor inserter.

The block has two different views for the back end and the front end.

The Hello World block in the block editor of the website.
The Hello World block in the block editor of the website.
The Hello World block on the frontend of the website.
The Hello World block on the frontend of the website.

Structure of the Block

This on overview of the files and directories contained in the Hello World block plugin directory:

hello-word
  |
  ├── build
  |  ├── block.json
  |  ├── index.asset.php
  |  ├── index.css
  |  ├── index.js
  |  ├── style-index.css
  |  ├── view.asset.php
  |  └── view.js
  |
  ├── node_modules
  |
  ├── src
  |  ├── block.json
  |  ├── edit.js
  |  ├── editor.scss
  |  ├── index.js
  |  ├── save.js
  |  ├── style.scss
  |  └── view.js
  |
  ├── .editorconfig
  ├── .gitignore
  ├── hello-world.php
  ├── package.json
  ├── package-lock.json
  └── readme.txt

Let’s take a look at what these files do.

Configuration files

  • .editorconfig contains configuration for the code editor that you are using. You can read more about what this file does at EditorConfig.org.
  • .gitignore is a starting point for which files to ignore from Git source control.

Main plugin file

The hello-world.php file contains the plugin headers, and the call to the register_block_type() function.

This PHP file reads the block.json from the build directory. This directory contains the built version of the plugin, which is different from the source code. We’ll look into how this build process works in the next section.

There is no other PHP code needed. The block configuration file handles everything from this point on.

The source directory

The src directory is where the source code for the block lives:

  • index.js is the central entry point for the build process. Therefore any JavaScript file that is not included here won’t be part of the build.

    This file also contains the code to register the block on the client side. And it includes the style.scss file, so that the build process can discover it, and build it into CSS.
  • edit.js contains the JavaScript code for the editor view (backend) of the code.
  • editor.scss contains the styles for the editor view of the block.
  • render.php only exists for dynamic blocks. It contains the PHP code for the frontend view.
  • save.js is only present for static blocks. It contains the JavaScript code to generate the markup for the frontend view.
  • style.scss contains the shared styles for both the frontend and the backend of your site.
  • view.js is always present, but mostly not needed. This file is for any JavaScript that your block might need on the frontend.

The build directory

The build directory contains the files built from source. It’s this code that powers the block in WordPress, and it gets generated from the source code.

  • block.json is copied over as-is from the source directory. This is because there are no changes done to this file.
  • index.asset.php is an internal file used to track the dependencies or your code.

    Whenever you include a package, like for example @wordpress/blocks in your JavaScript code, an entry for this package file is added here. That way only the dependencies that are needed are loaded.

    In addition this file also contains a version hash. This chain of characters identifies the current build version, and ensures that the browser will load your new block assets if needed.
  • index.css contains the compiled and minified Sass from the block editor-only styles.
  • index.js contains all the JavaScript for your block, transpiled and minified.
  • render.php is copied over as-is, is it is not necessary to make changes to the PHP.
  • style-index.css contains the compiled and minified Sass from the shared backend and frontend styles.
  • view.asset.php is an internal file used to track the dependencies of your frontend JavaScript file (the view.js). It works the same as index.asset.php
  • view.js contains the JavaScript for your frontend interactivity.

The Node files

The package.json file contains the list of NPM packages used by the project. It also registers the scripts that can be run on local via NPM.

The package-lock.json file contains the exact list of packages that you have installed. This is because usually packages use a version range, so for example anything in the 2.x branch.

The lock file contains the exact version installed, for example 2.3.1. This serves two purposes:

  1. Every developer that installs the project gets the exact same dependencies. This avoids different developers working with different versions.
  2. NPM can compare your installed versions with those available, and notify you about available updates.

The node_modules directory contains the source code of all the NPM packages used by the project. These files were downloaded from the NPM directory during the creation process of the plugin.

Changing the block boilerplate code

Let’s modify the boilerplate code to see how Create Block is used during development.

To clarify at this point, you are no longer working with the Create Block package. Instead you are working with the @wordpress/scripts package, also called WP Scripts.

It’s this package that provides all of the functionality described below.

Using the development mode

To do so, you need to switch into the hello-world directory, and run npm run start.

A screenshot of the Terminal with the WP Scripts development mode running.
A screenshot of the Terminal with the development mode running.

This will create a new build from the current source code. In addition, the files in the source directory are followed for any changes. This means that the build is refreshed whenever a change is done to any JavaScript or SCSS files.

Modifying code

We now can go into sr/editor.scss set the background property to #000. This is what the styles will look after the change:

.wp-block-wpdc-hello-world {
    background: #00;
    border: 1px dotted #f00;
}

I

When you now reload the Edit Post screen of the the Hello World post we created earlier, you’ll see that the background of the block has changed.

Our custom block with a modified background color.
A view of the modified Hello Word block in the editor.

How did this happen? When in development mode, all JavaScript and Sass files will be rebuild automatically on every change. You still need to reload the page though to see the changes.

Debugging issues

The React code generated in this mode is not optimised for production. Therefore if you run WordPress in development mode, you’ll be able to see error messages in the browser console when the block is broken.

An example of React errors displayed during development.
An example of React errors displayed during development.

In addition, the Terminal window in which you have run npm run start will display error messages for issues in the JavaScript code.

An example of a JavaScript error displayed during development.

Building production code

Once your block is ready, and you want to use it on a production website, you can run npm run build.

Conclusion

If you have gotten this far, then congratulations for completing the tutorial! You now should be ready to start building your own blocks.

If you’re looking to go beyond the basics, and truly master custom block development, check out my guide to learning custom block development.

Level Up Your WordPress Development Skills With One Email Per Week

Every Sunday, I send out tips, strategies, and case studies designed to help agencies and freelancers succeed with modern WordPress.

My goal is to go off the beaten path, and focus on sharing lessons learned from what I know best: building websites for clients.

100% free and 100% useful.

Feel free to check out the latest editions.