We tried converting a bespoke website design in WordPress with Gutenberg

and this is what happened

Photo by Iker Urteaga on Unsplash

This is what we asked Marie to do

I’m Simon, founder of Studio 24, a digital agency who create user-centered websites for our clients. I recently asked my WordPress Lead Developer Marie to research and test WordPress’s new Gutenberg editing system. The objective was to take a recent design and attempt to implement a few custom designed components in Gutenberg.

We used Gutenberg 2.9.1 during testing. The project is in constant development and there’s no clear release date (August 2018 has recently been suggested at WordCamp Europe). It’s an ambitious and interesting project and one that greatly interests me as an agency owner. Is Gutenberg right for us? Will it help our clients? Can we make money developing sites on it?

The rest of this article is Marie’s experiences learning and testing Gutenberg. Any constructive comments are appreciated. Please bear in mind she had a specific task which is to explore how suitable Gutenberg is for an agency like ours. Our use cases are not the same as everyone’s, but hopefully there is useful feedback for the wider community in this post. Now back to Marie.


As far as we are concerned, we don’t think we are going to implement our bespoke website designs using the Gutenberg editor just yet. The main reasons are:

  • the Gutenberg API is still very much in development,
  • so much so that even the official docs are out of date,
  • a few important features are still in their infancy or missing (overriding default blocks, nesting blocks, etc)
  • we estimate it would more than double our dev and QA time
  • updating blocks already used in the content is complicated

On the other hand, if you are releasing commercial themes, Gutenberg could be great news. You can rely on WordPress to provide flexible blocks of content and focus (almost) entirely on the CSS.

The Gutenberg exercise

We have used WordPress for the vast majority of our projects in the past few years. Gutenberg, planned for release as part of WordPress 5.0, changes quite drastically the content editing experience and WordPress development.

We are currently assessing Gutenberg as a viable option for our websites going forward. As part of that, I was tasked with attempting to convert a design produced by Ian, our creative director, into a WordPress website using Gutenberg. I think this is an interesting exercise because it is NOT really an exercise but a real business task. It is the actual design of our upcoming new agency website and I am doing this in parallel to another dev building the website the ‘traditional’ way. I cannot compromise on the result. It needs to match what the other dev has achieved.

More details on what we need to achieve and how we’ve done it so far

An important part of our job is implementing an interface that provides enough flexibility to create varied content but that is constrained enough to prevent breaking the design when editing a website.

To achieve this at the moment, we rely heavily on the advanced custom fields plugin (and Fewbricks) to create what we internally refer to as ‘flexible components’. ‘Flexible components’ are units of content or layouts. For example we have a standard text component, an image carousel component, a video component, etc. that users can add in any number and in any order to the content of their pages. This is really close to the concept of Gutenberg blocks, so we are very enthusiastic about Gutenberg’s core concepts.

Our flexible components work fine for the main content of pages but we also need ‘static components’ that will to stick to the top or bottom of the pages. We also need to implement templates that are more or less constrained for certain post types or pages, the homepage usually being the more structured and constrained template.

Code quality is high on our list. We need control over the website markup to ensure performance and SEO. For example, we need to make sure images in our components are fully responsive with image sources optimised for different screen sizes and aspect ratios.

In some places, a heading might be an H5 for semantic and SEO reasons but need to look like an H1 because that’s what the designer or client decided.

Getting prepared — A skill set U-turn

I personally have 10 years experience developing WordPress custom themes and on occasion, plugins. WordPress development so far requires the following skill set: strong knowledge of HTML and CSS, moderate to advanced level of PHP, a little JavaScript will do. (Although I have built up a decent knowledge of JavaScript over the years).

Now suddenly with Gutenberg I need to have a very good level of JavaScript, including a good knowledge of the React framework. PHP has become a bit of an afterthought.

So before I even embarked on this exercise, I spent time learning React. It required a significant mind shift to effectively use components, properties, states, etc. But eventually, after going through the official React tutorial and a few days work, I was able to code a little widget that calculates a total volume based on dimensions of a series of areas… No groundbreaking single-page app I concede but, most significantly, I was able to fulfil a set brief without compromising, and I became ‘autonomous’ in the sense that I was able to do something that was far enough from a mere copy of the tutorial.

I then set out to learn Gutenberg development. I started with reading the Gutenberg homepage, the official Gutenberg handbook, and a few interesting blog posts by Riad Benguella, JavaScript engineer at Automattic, on more specific topics such as various methods to extend Gutenberg. Simon, our director, also signed me up to an online course by Zac Gordon, which I worked through in its entirety.

Looking back at that point, I had already spent two weeks learning. I still didn’t have ‘real life’ development experience in Gutenberg. And I was already thinking: what happens if we need the whole team to go through that? And then go through the process of establishing our Gutenberg development best practices and tools?

‘Easing’ into it

Now before I enter into technical details, I can already tell you that I didn’t go far at all. After three days of work, I was ashamed to get back to the rest of the team with nothing to show to them. Here is what happened.

Whitelisting blocks

I thought I’d start with something simple. I wanted to reduce the number of blocks available by default, as many of them were not needed in our design. The Gutenberg handbook provides code for doing just that here: https://wordpress.org/gutenberg/handbook/extensibility/extending-blocks/#removing-blocks.

The issue is, that code doesn’t work. It took me a while to debug and reach an error message I could search on Google. This led me to this Github issue: https://github.com/WordPress/gutenberg/issues/4848 posted on the 3rd February. Apparently, the hook that was documented and at which we should load our scripts for shortlisting blocks is now loading ‘later’. No more precision from Automattic — see this reply from Riad Benguella that says

“These […] hooks are still being optimized, so this might change slightly in the future.”

🤔… The rest of the conversation are other developers suggesting their own solutions.

One of these solutions worked: waiting for the whole window to load before running the whitelisting script. It’s hacky. It’s not performant. But I had ‘wasted’ enough time; I wanted to move on and therefore decided I was done.

Removing block options

I then wanted to recycle the remaining blocks and restrict their options. For example, looking at the paragraph block I don’t want the users to pick colours or text size. These are defined in our bespoke design and we want to avoid inline CSS.

As I am writing this, I FINALLY found a way to remove the colour options from Gutenberg but only by trying my luck tinkering with code found in various blog posts. On the other hand, there is no way to remove the other options of the paragraph block.

You can find generic pointers as to how to modify blocks but:

  1. The docs are sparse. See for example this paragraph on modifying a block edit method: https://wordpress.org/gutenberg/handbook/extensibility/extending-blocks/#blocks-blockedit. There’s not a lot said about what is a complex operation. And there are hardly any code examples in that section.
  2. The modifications illustrated so far are too limited for our purpose. It did give me enough info to modify a block title and category but that’s all I could manage. We can append/prepend fields to a block but there’s no easy way to remove options, unless we try to override the block methods altogether?

I’m leaving a question mark at the end of this sentence because I never quite got to the bottom of the issue. The situation sent me into a wild internal debate as to whether it was wise to try and override these methods.

At some point I thought I’d take a look at a method I wanted to override in the Gutenberg plugin — which I had installed from the official plugins directory. The code was minified and I couldn’t find the unminified version in the plugin. I did the next best thing and looked for the code in the Gutenberg Github repo — hoping the code exactly matched that of the plugin directory. I wanted to copy and paste it in my code and start tinkering with it. But it’s using Modern JavaScript and JSX. I’m not.

There ensued yet another internal debate: should I upgrade my build tools and use Modern Javascript? The current state of things in the JS world compounds the difficulties anyone might already be having with Gutenberg itself. The official docs show code in ‘traditional’ JS, the Gutenberg repo on Github uses Modern JS. And this goes for all the tutorials out there: some in ‘traditional’ JS, some in Modern JS. So it’s difficult to copy and tinker with code, which would have been a great source of learning.

Building MY simple block (as opposed to ANY simple block)

So at this point, as I cannot remove all the options I need to remove from the paragraph block, I decide to write my own. This is my brief to myself:

  • create a block to input text,
  • the text needs be multiline (multiple paragraphs to be precise) and wrapped into a div with our own CSS classes,
  • there must be an option to add extra space before the block (more on that later).

I find code for a simple block in an exercise file I downloaded from the course on Gutenberg I did earlier in the year. I copy the code, paste it, and… things don’t go as planned.

The language barrier: what happened to localisation?

I can enter text in my new block but when I publish or update the page, the text has gone. Looking into the database, it hasn’t saved properly. I double-check my code against the original one — which was working fine when I did the course — I only changed a few minor things such as the name of the block.

My only clue turns up in my browser console in the form of the following error message: Jed localization error: Error domain ‘studio24-gutenberg’ was not found.

This leads me to the conclusion that the following line of code used to define the title of my block does not work anymore:

title: __( ‘Studio 24 paragraph’, ‘studio24-gutenberg’ )

More generally, localisation does not work anymore, at least not implemented as it is described in the docs. We need localisation, that’s not an optional feature for us.

It took me a whole morning to solve the issue. Just a few lines of code, but not fully documented anywhere.

I had to pull together information from the official WordPress and Jed docs, blog posts, Github issues, slides of an excellent presentation on the subject by Pascal Birchler, and I had to dig out an example of a translated block (also by Pascal Birchler) on Github (https://github.com/swissspidy/gutenberg-i18n-block).

And that was only to get the block NOT TO FAIL when Gettext is used. I haven’t gone as far as generating pot and mo files to provide translation data — which is apparently still a very inefficient process at this stage.

The shared CSS delusion — Workload multiplication

At this stage I have a block that can be edited and has the right markup elements. Good! Next step: adding styles to it. I don’t want to use inline CSS. I know I can add a CSS file per block but this block shouldn’t need any specific CSS, the website’s global CSS (for typography and generic spacing) should do.

I already have my website global CSS for the project and it works on my block in the front-end. I’m thinking I can be smart and adapt my build tools to produce an ‘editor.css’ file in parallel to my main css file (the one that loads in the front-end). Surely I can re-use the same global CSS rules.

It turns out I can’t. The Gutenberg editor has its own markup and CSS classes.

For example, I wanted to style the post title in the editor. It wasn’t a matter of simply targeting h1s or h2s. In order to override the Gutenberg editor styles applied to the page title, the selector ended up being .editor-post-title .editor-post-title__input.

Same thing for paragraphs in my block. The effective selector was not p but .edit-post-visual-editor p.

And I had to copy across the relevant CSS rules from my global CSS into my editor.css file. That doesn’t bode well for maintainability. Is it better to scatter and repeat these global rules in individual CSS files for each block? I don’t think so.

If there is a way of keeping one codebase for this global CSS and automate its distribution to each block and between front-end and editor, then it will require A LOT of careful planning and tooling. That sounds too brittle.

In some cases, you also need to work out the right CSS selector for when a block element is in focus, i.e. when it is being edited.

All in all, my estimate is that these things more then double up the CSS workload.

I did a bit of research on this issue and came across this very interesting blog post by Theme Shaper — the Automattic theme team themselves: https://themeshaper.com/2018/02/15/styling-themes-for-gutenberg/. They tried to write CSS-only themes for WordPress with Gutenberg, and one of their conclusion was:

“Setting up the block styles for the back-end editing experience was more involved than any of us had anticipated. It’s very much like adding editor styles to the current TinyMCE editor, but some Gutenberg blocks have very specific classes that needed to be overridden.”
Laurel Fulford of ThemeShaper.com, the Automattic Theme Division

This led me to another realisation: when we design a block, we also need to design its user interface (implemented in JS) and QA the user interaction. That’s a significant addition to my workload. At the moment, Advanced Custom field takes care of the UI for us.

Feedback pains — the deprecated method

What happens after internal QA and when client give their feedback? Again, we need to amend our CSS for the front-end, and for the back-end.

Things are even worse for markup amends. If the block has been used anywhere in the content, we have to write a migration function to map the content of the old markup into the new markup (in the deprecated method of the block — see https://wordpress.org/gutenberg/handbook/block-api/deprecated-blocks/). That in itself takes a fair bit of development and QA time on top of requiring solid JavaScript skills.

If that deprecation method does not exist and we change the markup, for example during development, we are faced with an error message. This quickly got very irritating and time consuming.

Every time I wanted to preview edited block markup…

The spacing conundrum — more code planning

Whilst I was working out these technical difficulties, a lot of other considerations were brewing at the back of my mind. An important one was: how do I decide what is a stand-alone block or what is a component that I can re-use in multiple blocks? Can I nest components and blocks?

Let me give you a concrete example. In the design I was handed, what we internally refer to as a ‘flexible component’, and that at first glance we would implement as a Gutenberg block, is a section of content with a 150px gap before or after it. Consider the following:

A lead paragraph block?

We call this a ‘lead paragraph’. That is a page introduction written in a larger font size and that typically sits under the page title. In the screenshot above it appears as a block in its own right.

Further in the design, I find this pattern in the middle of a page:

Top half of a webpage section

Now here we have a block made out of a heading, a lead paragraph and then some free text. In terms of design and content flow, that’s a block.

But we could also consider it to be a heading block, followed by a lead paragraph block and then a text block. Or we could consider it’s a block in which are nested a heading block, a lead paragraph block, and a text block.

It’s definitely not a ‘Classic editor’ (WYSIWYG) block because there is no way to format that lead paragraph via the WYSIWYG (or at least, if we end up customising the Classic editor block to that point, what’s the point of the other blocks?)

How do I implement these things? How do I plan my code for this situation?

Maybe I could implement these as separate blocks and define a ‘spacer’ block that the client can place between sections when they populate the website? Although that puts a lot of responsibility on the client, who are most probably going to forget about the spacer block altogether.

Maybe I keep them as separate and add a block option called ‘extra top spacing’ or ‘new section’ that the client can toggle to define a block as the start of a new section? That bears the same drawbacks as the previous solution.

Do I write super clever CSS so that extra top spacing is never added to an element that follows a heading and so on? That’s going to get very complex very quickly, even just to define all the patterns and use cases. And we’ll end up with rather obscure CSS.

Do I write these as reusable components that I can then use to build blocks with? That sounds ideal and I know that’s doable in theory but it also requires a LOT of work: going over the design again, listing all the possible components, implementing them, working out a good file structure, and only then implementing the blocks. This sounds like a lot for a first trial. And I have no guarantee this would go smoothly. Even if it does, this would take a LOT more time than what we are currently spending on building our flexible components using Advanced Custom Fields (and Fewbricks for code re-use), even if over time we grow and re-use our bank of components. Maybe it would be better if these base elements were coming from Gutenberg — and maybe they will.

Or is this what nested templates are for? I doubt it, templates come with their own limitations (see below) and I’d have to work out what container blocks are and how to implement them (This page on nested templates is the only place where the term ‘container block’ is mentioned as far as I can tell).

Were I to start this block breakdown debate in the office, we’d never get out of it.

In the end and in an attempt to get some results in a decent amount of time, I opt for adding an ‘extra top spacing’ option to my paragraph block. I knew we wouldn’t keep that solution eventually, but at least that would force me to work out how to add options to a block.

The final straw: the Block Inspector

I commented on my difficulties with CSS above but forgot to mention another issue I faced. WordPress provides a series of ‘components’ (in the sense of ‘React component’ to use in blocks). For example, the Toolbar component to hold controls for options above the block editing area, the Media Upload button for picking images from the media library, or the RichText component which allows multiline text input with a few extra controls.

I needed the RichText component. According to the Gutenberg handbook, we can get that component using wp.blocks.Richtext (https://wordpress.org/gutenberg/handbook/block-api/rich-text-api/). Except things have been re-organised since the publication of the handbook and now it’s wp.editor.RichText. Which makes sense; yet, I think that’s a big change NOT to be properly documented.

Coming back to my story, I now have a working and styled custom paragraph block. As I explained above, I want to add an option to toggle between normal spacing and wide spacing at the top of the block. Looking at existing WordPress blocks, I want to produce something that works like the ‘Drop cap’ toggle button of the Gutenberg paragraph block. See screenshot below:

The block inspector that appears on the right-hand side, under the ‘Block’ tab, when editing a Gutenberg block.

The area on the right-hand side that holds block options is called the block ‘Inspector’. There isn’t much said at all on how to create a block inspector in the handbook — you can see it all here: https://wordpress.org/gutenberg/handbook/blocks/block-controls-toolbars-and-inspector/#inspector. So I have to find guidance elsewhere.

I finally determine, by looking at code in the Gutenberg Github repo, that I need to create (or at least I think I need to create) an InspectorControls element containing a PanelBody element, itself containing a ToggleControls element. And then I need to make it all work so changing the option takes effect on the block markup.

I never managed to make the panel with the toggle control in appear. At all. Not even the panel title or some test content. I spent a few hours in the browser console and JS debugger just to work out how to refer to these elements (whether they were pulled from wp.blocks, wp.editor, wp.components).

All in all at that stage I had spent about three working days on this exercise. I hadn’t been able to build a single block that could be considered within the brief. My mind was completely muddled with technical and design considerations.

It occurred to me I might be wasting my time and therefore decided to end things there and call Simon (the director of the agency) to report on the state of affairs.

Things I knew I couldn’t achieve anyway

There are other things that I knew in advance I couldn’t achieve. I thought maybe workarounds or solutions would come up as I got used to Gutenberg development but you now know the story.

In the meantime, I know for a fact the following are not possible or too limited for our purpose.

Advanced templating

As mentioned at the beginning we need advanced templates in the sense that:

  • templates need a mix of ‘fixed’ components and ‘flexible’ components,
  • templates need to apply not only to different post types but also sometimes to specific (singular) posts.

I know there are plans to refine the Gutenberg templating options but at the moment options are too limited for our purpose. A template is defined as a set list of blocks. Templates can be assigned to custom post types but not to individual pages (such as page templates that currently exist: https://developer.wordpress.org/themes/template-files-section/page-template-files/).

There are only two options for ‘locking’ the blocks of a template: one that allows re-ordering the blocks of the templates and one that does not (if I understood well as I find the documentation ambiguous). No option allows to group blocks into sub-groups, some in which blocks are fixed and others in which blocks can be re-ordered.

Optimal image sizes

Looking at the design for a bespoke ‘quote’ block below.

This is not Simon Jones

We have a text/paragraph field, an image field and another text field for the signature. My issue is with the image.

We want the user of the website to be able to upload a large image (most of our clients are not familiar with image editing tools) but for a small version of the image to be loaded in the front-end to minimise load times.

The MediaUpload component of Gutenberg implements the interface for adding images in blocks. Unfortunately (as far as I can see) that component only returns the URL of the full size image as opposed to an array of all the image sizes available.

We spent a significant amount of time this year working out best practices relating to image sizes. Currently WordPress allows us to implement these best practices by defining our custom image sizes used for various screen sizes and aspect ratios (using the add_image_size() function) and accessing the appropriate images sizes in our theme. That doesn’t seem to be possible yet with Gutenberg.

Teasers — Complex references to other posts with manual overrides

How do we implement the block of teasers below?

Teasers leading to other pages of content

Taking into consideration that:

  • We usually give the client the ability to select posts manually (using the post object’ advanced custom field)
  • By default each page title, permalink, excerpt and thumbnail are picked up dynamically based on the selected post objects
  • We often add the ability to override the default title, excerpt and thumbnail manually for each entry

Even if we strip these functionalities down the bare minimum (picking individual posts), I haven’t come across any relational field. The dynamic blocks implemented so far in Gutenberg (the latest posts and categories blocks) are far simpler.

In theory we can build this block via React and AJAX calls. But it’s far more work than this requires at the moment.

There are yet other features that I know are in the works or have been requested but not yet usable in practice, such as nested blocks and repeater blocks.

Main conclusions

Gutenberg is still very much in development and it needs to at least stabilise before we attempt this exercise again.

Throughout this whole experience, I was always aware that my lack of achievement with this exercise might simply be down to my limited knowledge of Gutenberg and React (I think most of us developers have been through the experience of frustration and hatred for a tool or language until we mastered it).

Yet in the context of providing services to clients, we have to be pragmatic. There is only so much time we can invest in exploring the various features and constraints of a new tool — and in conveying that knowledge to the whole team.

Most of all when a tool seems very much still in development. I could have gone further in my code analysis and tooling, but what if the Gutenberg API changed before I had to report to the rest of the team?

Currently, the lack of good documentation makes using Gutenberg difficult and risky

I spent hours cross-referencing tutorials, blog posts and Issues from Github to implement the most fundamental things (internationalisation for example).

Gutenberg is in such a state of flux that even its official documentation is out of date.

There definitely isn’t enough documentation and tutorials out there on advanced Gutenberg development, or should I say on not-super-simplistic use cases. You can find quite a few introductions to building your first, single field block (with code that is very similar to the few examples provided in the official Gutenberg Handbook) but not much at all on ‘real life’ advanced block development.

Of course, we can expect this to improve with time. But we would need it to happen quickly enough to get prepared before Gutenberg is released.

Steep increase in development and QA time

Were we to implement one of our current websites with Gutenberg now, we estimate that the extra CSS work required to style blocks in the editor and the complexity of updating block markup would more than double our development and QA time.

And that’s not counting the time to invest in coming up with internal best practices, build tools and a potential bank of re-usable components.

And maybe we’re simply not Gutenberg’s target audience

I am sure Gutenberg will greatly improve the experience of users who put their website together themselves and use themes provided by WordPress to do so.

I suspect some companies selling commercial themes will benefit from Gutenberg. Among those who are currently building their own rich editor or relying a plugins such as Visual Composer, some might be happy to rely entirely on blocks provided in core WordPress and focus on CSS work. It would be interesting to hear their take on Gutenberg.

As an agency building bespoke websites based on the WordPress CMS, the future of our relationship with WordPress is in a state of flux. We’re interested to revisit this once Gutenberg is in a more finished state, but we fear some of the problems we encountered might persist. We’ll wait, (test again) and see…