With Wordpress 5, Gutenberg has introduced a (nearly) modular experience for content creation, allowing for amazing customization previously not seen in the open-source world. Gutenberg also has an active port for Drupal, and even allows Drupal modules to be inserted into pages and promises full compatibility between Wordpress and Drupal. Suddenly Gutenberg seems like the solution for the woes of CMSes.

A Brief overview of Gutenberg's workings

Gutenberg works because of it's simplicity. CMSes previously always fell apart when the user wanted to enter content that a template was equipped to handle. This meant adding fields and/or modifying/creating a new template. The way Gutenberg approaches this is to simply store HTML with flags around the content to define a Gutenberg block. Rather than using multiple database fields, Gutenberg stores its data within the post-body. This in itself isn't novel, but how it's handled is.

A Gutenberg block has two presentations:

  • An editor view visible when creating a page or post
  • The rendered page (front end) that a regular visitor sees

Where Gutenberg is clever is that the block for the admin view, the markup is parsed into a React component, and the states for the component are captured and written into the block as the developer sees fit. A Gutenberg block can actually consist of Gutenberg blocks inside Gutenberg blocks, meaning developers can leverage pre-existing blocks to create new blocks.

The big downfall is that the markup is very fragile. If you were to change a Gutenberg block's HTML output, all previous blocks will result in errors such as “This block appears to have been modified externally”. Gutenberg does include validation.

Where Web Components come in

Below is the save function for a really simple Image block I wrote.

      save: props => {
            const { imgURL, imgAlt,  imgURLSmall, selectControl } = props.attributes;
          return (
              <div className={selectControl} >
                <picture>
                  <source srcset={ imgURL }   media="(min-width: 992px)" /  >
                  <img src={ imgURLSmall } alt={ imgAlt }/>
                </picture>
                  <caption>{imgAlt}</caption>
              </div>
          );
      },
    

Let's say, at a later date I wanted to change how my image block renders, and changed markup :

      save: props => {
            const { imgURL, imgAlt,  imgURLSmall, selectControl } = props.attributes;
          return (
              <div className="responsive-image">
                <picture>
                  <source srcset={ imgURL }   media="(min-width: 992px)" /  >
                  <img src={ imgURLSmall } alt={ imgAlt }/>
                </picture>
                <div className={ selectControl}><caption>{imgAlt}</caption></div>
              </div>
          );
      },
    

You'll notice that it now has an image container with a different class, and the caption now has a parent div. Every image on the site would now be receiving a “This block appears to have been modified externally”. One vector would be validation, but an even simpler solution would be to avoid this error by using a web-component. In this hypothetical, I've offloaded all the rendering to a web component, called my-image

      save: props => {
            const { imgURL, imgAlt,  imgURLSmall, selectControl } = props.attributes;
          return (
              <my-image src={imgURL} alt={imgAlt} small-image={imgURLSmall} selectControl={selectControl}></my-image>
          );
      },
    

Not only do we consolidate all the markup to prevent validation problems, we also have the bonus of the web component world. Any frontside JS features, perhaps a lightbox for our responsive image, could be handled, complete with encapsulated CSS. The opportunities only expand as you leverage slotted content.

I plan to update this post with actual code demos soon. Stay tuned.