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:

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).
- we specify a
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:

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)
...
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/scripts
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"
}
}
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!' );
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() {
wp_enqueue_script(
'gutenberg-button',
GUTENBERG_BUTTON_URL . '/build/index.js',
[],
GUTENBERG_BUTTON_VERSION
);
}//end enqueue_script()
add_action(
'enqueue_block_editor_assets',
__NAMESPACE__ . '\enqueue_script'
);
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:

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:

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

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';
wp_enqueue_script(
'gutenberg-button',
GUTENBERG_BUTTON_URL . '/build/index.js',
$asset['dependencies'],
$asset['version']
);
}//end enqueue_script()
add_action(
'enqueue_block_editor_assets',
__NAMESPACE__ . '\enqueue_script'
);
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.
Conclusions
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.