How to build a Gutenberg block plugin

Gutenberg is on its way. Whatever you think about the rights and wrongs of its implementation, it will undoubtedly offer more possibilities to people building WordPress sites. In this tutorial, I’m going to show you how to build a Gutenberg block plugin.

Enqueuing block assets

With the main file ready, we can start to think about enqueuing our plugin’s assets. If you are familiar with developing in WordPress, the first thing to note about Gutenberg is that development is mostly in JavaScript, not PHP.

With that in mind, we’ll need to enqueue the following assets:

block.js file – the file where we register and build the block itself

editor.css – the styles for the block in the editor

style.css – the styles for the block on the front-end

Unless there are differences in style between the editor and front-end, I recommend working on your styles in the style.css file. That file will be enqueued into both the front end and the editor. If you need to add any editor-specific styles, you can add them to the editor.css file.

In this tutorial, the editor.css file will actually be empty but I’m enqueuing it here anyway for the sake of completeness.

Our file structure

This plugin uses the following file structure:

You might want to get your folders and files set up ready. You can add empty files to begin with.

Script dependencies

wp-blocks – this is the JavaScript library in Gutenberg that handles block registration and related functions

wp-element – the library that handles the block UI

wp-i18n – the internationalization library

Use filemtime for version

Also note the use of filemtime for the version parameter (filemtime gets the last modified time of the file). Often in plugins, we might just use the plugin version number here. Gutenberg needs the last modified time to ensure it has the most recent version of the file, otherwise updates you’ve made won’t be available when you try to preview or update a post.

Okay, that’s the basic plugin structure ready. Now we just need to start filling in the gaps.

The block.js file

The block.js file is where all the action happens. As I mentioned above, development in Gutenberg is through JavaScript. We start by making a wrapper for our code. I’m going to include some placeholder comments so that we can start dropping more code in as we progress.

Note that you are pulling through some global elements from the wp JavaScript object as outlined above, i.e. blocks, element and i18n. We can take a more detailed look at each of these before we start using them.

Gutenberg wp.blocks

The blocks library contains elements related to UI and functionality. This includes components like editable areas, media upload buttons, alignment toolbars and so on – clearly elements that will be useful in creating your block.

Gutenberg wp.element

The element directory is an abstraction layer on top of React.js – the JavaScript framework behind Gutenberg. React is out of scope for this tutorial, but you can read more about it on Github. In essence, element allows you to create elements in the DOM.

Gutenberg wp.i18n

This is possibly the most familiar concept to anyone who develops in WordPress: i18n deals with internationalization. We will see some examples of that in the code below. You can read more about it on Github here.

Setting up our plugin’s variables

The first thing we’re going to do in our block.js file is use the different elements we’ve pulled through from the global wp variable to create variables for our plugin.

In place of the comment /* Set up variables */ you can add the following code:

Let’s look at what each of these is going to accomplish in the plugin:

var el = element.createElement;

This imports createElement from React. We’ll use this to create our DOM elements, like div, img, p etc.

var BlockControls = wp.blocks.BlockControls;

BlockControls give us access to the controls toolbar that appears when our block is being edited:

var MediaUploadButton = wp.blocks.MediaUploadButton;

MediaUploadButton gives us access to a media upload button, allowing us to upload our image or icon via the standard WordPress media library.

var InspectorControls = wp.blocks.InspectorControls;

InspectorControls are additional setting controls for our block. These aren’t rendered in the controls toolbar but in the Inspector panel:

var SelectControl = wp.blocks.InspectorControls.SelectControl;

SelectControl gives us access to a select field that we can add to the inspector panel, as above.

With all our variables and dependencies set up, we can register our block type.

registerBlockType

The registerBlockType function implements your block’s content. For a fuller write-up, check out the Gutenberg handbook entry on writing your first block. For now, we’ll look at its main parameters. Add the following code to your block.js file instead of the /* Register block type */ placeholder.

Firstly, notice that you need to specify the name of your block, including a namespace, in this case gfblocks/feature-block.

Secondly, note that you can add certain parameters as follows:

title: i18n.__( 'Feature' ),

Title is, obviously, the title of our block. Note that we have used the i18n declaration with the double underscore function to wrap our title. It’s not necessary to include a text domain.

icon: 'info', // Dashicon icon for our block

The icon parameter allows us to specify an icon to accompany the title. Use the dashicons library for ease: just remove the dashicons- prefix from the icon you want to use to get its slug. If you want to use a custom icon, check out this article on using an svg icon.

category: 'common', // The category of the block.

Choose a category for your block. This can be one of the following:

common

formatting

layout

widget

embeds

The next line in our code is this:

attributes: {},

Which means it’s time to add some more code to our example.

Gutenberg block attributes

The attributes property is how Gutenberg remembers the content of a block and knows how to render it.

In this example, we’re creating an attribute with a unique name that will find the element with the specified class name, then extract the src attribute, and store that data as a string. Later on, when we look at rendering our block content, Gutenberg will use the selector attribute so it’s important that these are unique for each attribute.

We first check to see if the block has focus (otherwise we don’t display the toolbar). We then extend the default toolbar by adding the AlignmentToolbar that we imported from wp.blocks at the top of the file.

We use the onChangeAlignment event handler that we defined earlier for when the alignment element is clicked.

Gutenberg InspectorControls

We saw above that we can use InspectorControls to add controls to the inspector panel in the sidebar. We can see from this snippet of code how we are including a select field in the inspector panel to allow us to choose between a one and two columns layout.

So we use el first to create the wrapper div. We create a dynamic class name using the value of attributes.columns in order to manipulate the layout depending on whether we are displaying one or two columns.

Then we use el again to create the div with the class gfblocks-block gfblocks-block-1 and we continue by creating a button element, an H3 element, and a p element. We repeat the whole thing for the second feature.

In many ways, this is similar to the edit function. We’re using el to create our elements then we’re populating them with the values of the attributes.

Block CSS

I mentioned at the start of the article that there are two CSS files enqueued: style.css is enqueued in the editor and on the front-end and editor.css is enqueued in the editor only. Because there is no extra CSS necessary in the front-end, I’ve placed all the styles in style.css.

Typical Gutenberg error messages

At the time of writing, Gutenberg 2.0 has just been released, and there are a couple of common error messages you might encounter while developing your blocks.

This block appears to have been modified externally. Overwrite the external changes or Convert to Classic or Custom HTML to keep your changes.

I encountered this error whenever the block validation failed – for instance, if I’d updated the block and got the attribute selectors mismatched. It’s possible to view the page in the page inspector where you’ll find some more information on the failure.

This block has encountered an error and cannot be previewed

This error message is very generic. Most commonly, I found that I encountered this error when I’d made an error in the JS – mistyping a variable name, for instance. Again, you’ll find more information in the page inspector.

I anticipate that error messages might become more specific further down the line.

Resources for Gutenberg developers

It’s early days yet and no doubt the number of resources available will start multiplying exponentially. I found the following to be useful:

Hi Gareth
Thanks for your tutorial.
I have install your plugin and I have one question : Is it possible to delete an image.
I mean it’s possible to delete the block or to replace one image by another but is it possible to delete an image of the block ?

Your article is by far the best tutorial I’ve found until now on gutenberg. 😀
I just have one question and it’s about array type . I notice you use it to get text like with textTwo.
Is it possible to use it like a javascript array. I mean to get array of letter [“M”, “T”, “W”, “R”, “F”, “S”, “S”] or
number [12, 19, 3, 17, 28, 24, 7] ?