Traffic light button, by Ashim D'Silva

Almost a year and a half ago, Antonio wrote this blog post explaining one of the difficulties we faced when adapting our plugins to the new WordPress block editor. The result of his tutorial looked something like this:

If everything went well, the new button will appear in the text blocks.
Button we added to Gutenberg in a 2019 tutorial.

Fortunately or unfortunately, Gutenberg has changed a lot in this year and a half. The development stack has been expanding and improving and plugin and theme developers had to embrace and adapt the new technologies. And those of us who also write about our experience and share what we learn are now “forced” to update our tutorials so that you can keep up to date. But we’re happy about it!

A few weeks ago, Ivan, one of our readers, left us a comment in Antonio’s tutorial asking for help. Apparently he wasn’t able to implement Antonio’s plugin. And, to be honest, this doesn’t surprise me, because things have changed a lot recently. So, to help Ivan and all of you who read us and want to continue learning about WordPress, let’s recreate the tutorial on how to add a button to the Gutenberg block editor taking advantage of all the new tools that WordPress offers us!

Create a plugin

The first thing we must do is create a WordPress plugin. This is quite straightforward. Basically, all we have to do is create a folder in wp-content/plugins with the name that we want to give our plugin (for example, gutenberg-button) and, within it, create a file with the same name and a .php extension. Then type the following code in your plugin file:

Now, let’s take a closer look at what the previous snippet does:

  • First we open a <?php tag. No surprises here.
  • Next, in this main file, we add a multi-line comment. The comment includes several lines with “Key / Value” pairs. For example, we see how we specify the name of the plugin (Plugin Name), its version (Version) or the name of the author (Author). All this information will then be visible in the Plugins section within WordPress.
  • Finally, we add some boilerplate code:
    • we specify a namespace (we talked about namespaces here),
    • we make sure that, if the file runs, it’s run as part of WordPress, and
    • we define some constants about the plugin (which will be helpful later on).

Once we have done all this, if we go to the Plugins screen of our WordPress, we will see that the Gutenberg Button is there:

Example plugin to extend Gutenberg
The plugin we just created is now available to use. Brilliant!

we activate it and… voila! Sure, it won’t do anything, but it’s already there.

JavaScript plugin development

Nowadays, WordPress developers have to be profficient with JavaScript. That’s one of the consequences of Gutenberg being in core, I guess. And this tutorial is no exception.

Preparing the environment

If we want to add a new button to the Gutenberg interface, we must code this feature in JavaScript. So let’s prepare the JavaScript development environment in our plugin. To do this, simply run the following command from your command line (make sure you’re in wp-content/plugins/gutenberg-button when doing so):

npm init

and follow the instructions:

This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields and exactly what they do.                                                                                                                                                                                                        
Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (gutenberg-button)
version: (1.0.0)
description: Adding a formatting button in Gutenberg.
entry point: (index.js)
...Code language: CSS (css)

The result of this process is a package.json file. As you’ll see in a few moments, this file will be extremely helpful in the future.

As I have already revealed in the title of this post, we will use @wordpress/scripts to create our plugin. So let’s add it as a dependency by running the following command:

npm install --save-dev @wordpress/scriptsCode language: CSS (css)

This command will download a bunch of dependencies inside our plugin (under node_modules) and will modify our package.json so that it’s clear that @wordpress/scripts is now a development dependency.

If you take a look at the documentation of this package, you will see that it includes a lot of scripts to build, validate syntax, format code, etc:

  "scripts": {
    "build": "wp-scripts build",
    "check-engines": "wp-scripts check-engines",
    "check-licenses": "wp-scripts check-licenses",
    "format:js": "wp-scripts format-js",
    "lint:css": "wp-scripts lint-style",
    "lint:js": "wp-scripts lint-js",
    "lint:md:docs": "wp-scripts lint-md-docs",
    "lint:md:js": "wp-scripts lint-md-js",
    "lint:pkg-json": "wp-scripts lint-pkg-json",
    "packages-update": "wp-scripts packages-update",
    "start": "wp-scripts start",
    "test:e2e": "wp-scripts test-e2e",
    "test:unit": "wp-scripts test-unit-js"
}Code language: JSON / JSON with Comments (json)

so let’s edit our package.json file so that the "scripts" section contains all the recommended commands.

How to verify that everything works…

Let’s create a src folder at the root of your project and add an index.js file inside it. This will be the main JavaScript file of our plugin and will contain all your code (you can then organize the code as you please, as long as the main file is src/index.js).

Let’s try out if things work as expected by adding the following statement index.js:

console.log( 'Hi!' );Code language: JavaScript (javascript)

and building the project using npm run build. This will transpile your code into something that a browser can run (it wasn’t actually necessary right now, but it’ll be in just a couple of minutes) and generate a new script inside a build folder.

All we have to do now is tell WordPress this script exists so that it can load it. To do so, simply open the main file of your plugin (gutenberg-button.php) and add the following lines at the end:

function enqueue_script() {
    GUTENBERG_BUTTON_URL . '/build/index.js',
}//end enqueue_script()
  __NAMESPACE__ . '\enqueue_script'
);Code language: PHP (php)

If you pay attention you’ll see we’re simply telling WordPress to enqueue our new script /build/index.js as a block editor resource. This way, when a user accesses the block editor, our script will be part of the assets that the editor will include.

So let’s check this out. Go to your WordPress Dashboard, edit a post and look at your browser’s JavaScript console. If things went as expected, you should see “Hi!” written on the console:

Quick check that the script is glued and working
Quick check that the script is properly enqueued and working.

Replicating our tutorial to add a button to Gutenberg

Okay, now that we’ve seen that we can write JavaScript code and npm run build it into something our browsers will understand, it’s time to replicate Antonio’s tutorial. And this, dear reader, is extremely simple.

Open the src/index.js file and replace the previous console.log statement with the following:

As you can see, this is almost the same code Antonio wrote a few months ago. The main difference is the fact that we’re no longer using the global variable wp to access to Gutenberg’s functions and components; instead, we now rely on import statements. But other than that, it’s pretty much the same.

Once you have the code written, just npm run build it and that’s it! You now have the button in Gutenberg:

New button in Gutenberg
New button in Gutenberg.

Let’s make sure it works by selecting some text and clicking on the button:

Result of clicking on the button that we have added in Gutenberg
Result of clicking on the button that we have in the editor.

and there you go, we see the text shows up in the console again!

A final note on dependencies…

If you take a look inside the build folder, youll see that @wordpress/scripts has not only created an index.js file, but has an index.asset.php file. This file defines a small object with two properties:

  • a list of dependencies (namely, WordPress scripts) required by our plugin
  • a build version

We can (and should) use both of these properties when enqueuing our script in WordPress if we want to make sure the script will run properly. To do so, simply go back to gutenberg-button.php and change it as shown below:

function enqueue_script() {
  $asset = include GUTENBERG_BUTTON_PATH . '/build/index.asset.php';
    GUTENBERG_BUTTON_URL . '/build/index.js',
}//end enqueue_script()
  __NAMESPACE__ . '\enqueue_script'
);Code language: PHP (php)

Simply load the object in index.asset.php using an include statement and replace the list of dependencies we had ([]) with the actual dependencies and use the build number as the plugin version.


Creating really useful WordPress plugins is tricky. You must understand well how JavaScript works and be familiar with all the resources WordPress has. But thanks to the @wordpress/scripts package, preparing the JavaScript dev environment and building a JavaScript plugin that can run within WordPress is easier than ever.

I hope you liked today’s post. And, as always, if you get stuck at any point or have questions, please leave a comment and we’ll help you out.

Oh and, by the way, here is a link to the project, ready to be downloaded and tested if you wish so. Just clone the project, npm install all the dependencies, npm run build it and give it a shot! 😉

Featured image by Ashim D’Silva on Unsplash.

2 responses to “How to Add a Button to the Gutenberg Editor using @wordpress/scripts”

  1. Jon Avatar

    I was able to get the button working just as you described! But I had trouble getting the button to do what I want. Instead of printing to the console, I’d like it to insert just plain text (like “Hello world”) at the cursor position when the button is clicked. Can you point me to a good example, or give me an example of a function that could do this?

    thank you.

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.