How to Build a Nearly Headless WordPress Website

I believe that a traditional WordPress theme should be able to work as effectively as a static site or a headless web app. The overwhelming majority of WordPress websites are built with a good ol’ fashioned WordPress theme. Most of them even have good caching layers, and dependency optimizations that make these sites run reasonably fast. But as developers, we have accomplished ways to create better results for our websites. Using a headless WordPress has allowed many sites to have faster load speeds, better user interactions, and seamless transitions between pages.

The problem? Maintenance. Let me show you another possibility!

Let’s start by defining what I mean by “Traditional” WordPress, “Headless” WordPress, and then “Nearly Headless” WordPress.

Traditional WordPress websites

Traditionally, a WordPress website is built using PHP to render the HTML markup that is rendered on the page. Each time a link is clicked, the browser sends another request to the server, and PHP renders the HTML markup for the site that was clicked.

This is the method that most sites use. It’s the easiest to maintain, has the least complexity in the tech, and with the right server-side caching tools it can perform fairly well. The issue is, since it is a traditional website, it feels like a traditional website. Transitions, effects, and other stylish, modern features tend to be more difficult to build and maintain in this type of site.

Pros:

  1. The site is easy to maintain.
  2. The tech is relatively simple.
  3. There is great compatibility with WordPress plugins.

Cons:

  1. Your site may feel a little dated as society expects app-like experiences in the browser.
  2. JavaScript tends to be a little harder to write and maintain since the site isn’t using a JavaScript framework to control the site’s behavior.
  3. Traditional websites tend to run slower than headless and nearly headless options.

Headless WordPress websites

A headless WordPress website uses modern JavaScript and some kind of server-side RESTful service, such as the WordPress REST API or GraphQL. Instead of building, and rendering the HTML in PHP, the server sends minimal HTML and a big ol’ JavaScript file that can handle rendering any page on the site. This method loads pages much faster, and opens up the opportunity to create really cool transitions between pages, and other interesting things.

No matter how you spin it, most headless WordPress websites require a developer on-hand to make any significant change to the website. Want to install a forms plugin? Sorry, you probably need a developer to set that up. Want to install a new SEO plugin? Nope, going to need a developer to change the app. Wanna use that fancy block? Too bad — you’re going to need a developer first.

Pros:

  1. The website itself will feel modern, and fast.
  2. It’s easy to integrate with other RESTful services outside of WordPress.
  3. The entire site is built in JavaScript, which makes it easier to build complex websites.

Cons:

  1. You must re-invent a lot of things that WordPress plugins do out of the box for you.
  2. This set up is difficult to maintain.
  3. Compared to other options, hosting is complex and can get expensive.

See “WordPress and Jamstack” for a deeper comparison of the differences between WordPress and static hosting.

I love the result that headless WordPress can create. I don’t like the maintenance. What I want is a web app that allows me to have fast load speeds, transitions between pages, and an overall app-like feel to my site. But I also want to be able to freely use the plugin ecosystem that made WordPress so popular in the first place. What I want is something headless-ish. Nearly headless.

I couldn’t find anything that fit this description, so I built one. Since then, I have built a handful of sites that use this approach, and have built the JavaScript libraries necessary to make it easier for others to create their own nearly headless WordPress theme.

Introducing Nearly Headless WordPress

Nearly headless is a web development approach to WordPress that gives you many of the app-like benefits that come with a headless approach, as well as the ease of development that comes with using a traditional WordPress theme. It accomplishes this with a small JavaScript app that will handle the routing and render your site much like a headless app, but has a fallback to load the exact same page with a normal WordPress request instead. You can choose which pages load using the fallback method, and can inject logic into either the JavaScript or the PHP to determine if the page should be loaded like this.

You can see this in action on the demo site I built to show off just what this approach can do.

For example, one of the sites implementing this method uses a learning management system called LifterLMS to sell WordPress courses online. This plugin has built-in e-commerce capabilities, and sets up the interface needed to host and place course content behind a paywall. This site uses a lot of LifterLMS’s built-in functionality to work — and a big part of that is the checkout cart. Instead of re-building this entire page to work inside my app, I simply set it to load using the fallback method. Because of this, this page works like any old WordPress theme, and works exactly as intended as a result — all without me re-building anything.

Pros:

  1. This is easy to maintain, when set-up.
  2. The hosting is as easy as a typical WordPress theme.
  3. The website feels just as modern and fast as a headless website.

Cons:

  1. You always have to think about two different methods to render your website.
  2. There are limited choices for JavaScript libraries that are effective with this method.
  3. This app is tied very closely to WordPress, so using third party REST APIs is more-difficult than headless.

How it works

For something to be nearly headless, it needs to be able to do several things, including:

  1. load a page using a WordPress request,
  2. load a page using JavaScript,
  3. allow pages to be identical, regardless of how they’re rendered,
  4. provide a way to know when to load a page using JavaScript, or PHP, and
  5. Ensure 100% parity on all routed pages, regardless of if it’s rendered with JavaScript or PHP.

This allows the site to make use of progressive enhancement. Since the page can be viewed with, or without JavaScript, you can use whichever version makes the most sense based on the request that was made. Have a trusted bot crawling your site? Send them the non-JavaScript version to ensure compatibility. Have a checkout page that isn’t working as-expected? Force it to load without the app for now, and maybe fix it later.

To accomplish each of these items, I released an open-source library called Nicholas, which includes a pre-made boilerplate.

Keeping it DRY

The biggest concern I wanted to overcome when building a nearly-headless app is keeping parity between how the page renders in PHP and JavaScript. I did not want to have to build and maintain my markup in two different places — I wanted a single source for as much of the markup as possible. This instantly limited which JavaScript libraries I could realistically use (sorry React!). With some research, and a lot of experimentation, I ended up using AlpineJS. This library kept my code reasonably DRY. There’s parts that absolutely have to be re-written for each one (loops, for example), but most of the significant chunks of markup can be re-used.

A single post template rendered with PHP might look like something like this:

<?php
if ( have_posts() ) {
  while ( have_posts() ) {
    the_post();
    if ( is_singular() ) {
      echo nicholas()->templates()->get_template( 'index', 'post', [
        'content' => Nicholas::get_buffer( 'the_content' ),
        'title'   => Nicholas::get_buffer( 'the_title' ),
      ] );
    }
  }
}
?>

That same post template rendered in JavaScript, using Alpine:

<template x-for="(post, index) in $store.posts" :key="index">
  <?= nicholas()->templates()->get_template( 'index', 'post' ) ?>
</template>

Both of them use the same PHP template, so all of the code inside the actual loop is DRY:

$title   = $template->get_param( 'title', '' );

// Get the title that was passed into this template, fallback to empty string.
$content = $template->get_param( 'content', '' ); // Get the cotent passed into this template, fallback to empty string.

?>
<article x-data="theme.Post(index)">
  <!-- This will use the alpine directive to render the title, or if it's in compatibility mode PHP will fill in the title directly -->
  <h1 x-html="title"><?= $title ?></h1>
  <!-- This will use the Alpine directive to render the post content, or if it's in compatibility mode, PHP will fill in the content directly -->
  <div class="content" x-html="content"><?= $content ?></div>
</article>

Related: This Alpine.js approach is similar in spirit to the Vue.js approach covered in “How to Build Vue Components in a WordPress Theme” by Jonathan Land.

Detect when a page should run in compatibility mode

“Compatibility mode” allows you to force any request to load without the JavaScript that runs the headless version of the site. When a page is set to load using compatibility mode, the page will be loaded using nothing but PHP, and the app script never gets enqueued. This allows “problem pages” that don’t work as-expected with the app to run without needing to re-write anything.

There are several different ways you can force a page to run in compatibility mode — some require code, and some don’t. Nicholas adds a toggle to any post type that makes it possible to force a post to load in compatibility mode.

Along with this, you can manually add any URL to force it to load in compatibility mode inside the Nicholas settings.

These are a great start, but I’ve found that I can usually detect when a page needs to load in compatibility mode automatically based on what blocks are stored in a post. For example, let’s say you have Ninja Forms installed on your site, and you want to use the validation JavaScript they provide instead of re-making your own. In this case, you would have to force compatibility mode on any page that has a Ninja Form on it. You could manually go through and add each URL as you need them, or you can use a query to get all of the content that has a Ninja Forms block on the page. Something like this:

add_filter( 'nicholas/compatibility_mode_urls', function ( $urls ) {
  // Filter Ninja Forms Blocks
  $filtered_urls = Nicholas::get_urls_for_query( [
    'post_type' => 'any',
    's' => 'wp:ninja-forms/form', // Find Ninja Forms Blocks
  ] );

  return array_merge( $urls, $filtered_urls );
} );

That automatically adds any page with a Ninja Forms block to the list of URLs that will load using compatibility mode. This is just using WP_Query arguments, so you could pass anything you want here to determine what content should be added to the list.

Extending the app

Under the hood, Nicholas uses a lightweight router that can be extended using a middleware pattern much like how an Express app handles middleware. When a clicked page is routed, the system runs through each middleware item, and eventually routes the page. By default, the router does nothing; however, it comes with several pre-made middleware pieces that allows you to assemble the router however you see-fit.

A basic example would look something like this:

// Import WordPress-specific middleware
import {
  updateAdminBar,
  validateAdminPage,
  validateCompatibilityMode
} from 'nicholas-wp/middlewares'

// Import generic middleware
import {
  addRouteActions,
  handleClickMiddleware,
  setupRouter,
  validateMiddleware
} from "nicholas-router";

// Do these actions, in this order, when a page is routed.
addRouteActions(
  // First, validate the URL
  validateMiddleware,
  // Validate this page is not an admin page
  validateAdminPage,
  // Validate this page doesn't require compatibility mode
  validateCompatibilityMode,
  // Then, we Update the Alpine store
  updateStore,
  // Maybe fetch comments, if enabled
  fetchComments,
  // Update the history
  updateHistory,
  // Maybe update the admin bar
  updateAdminBar
)

// Set up the router. This also uses a middleware pattern.
setupRouter(
  // Setup event listener for clicks
  handleClickMiddleware
)

From here, you could extend what happens when a page is routed. Maybe you want to scan the page for code to highlight, or perhaps you want to change the content of the <head> tag to match the newly routed page. Maybe even introduce a caching layer. Regardless of what you need to-do, adding the actions needed is as simple as using addRouteAction or setupRouter.

Next steps

This was a brief overview of some of the key components I used to implement the nearly headless approach. If you’re interested in going deeper, I suggest that you take my course at WP Dev Academy. This course is a step-by-step guide on how to build a nearly headless WordPress website with modern tooling. I also suggest that you check out my nearly headless boilerplate that can help you get started on your own project.


The post How to Build a Nearly Headless WordPress Website appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Just How Niche is Headless WordPress?

I wonder where headless WordPress will land. And by “headless” I mean only using the WordPress admin and building out the user-facing site through the WordPress REST API rather than the traditional WordPress theme structure.

Is it… big? The future of WordPress? Or relatively niche?

Where’s the demand?

Certainly, there is demand for it. I know plenty of people doing it. For instance, Gatsby has a gatsby-source-wordpress plugin that allows you to source content from a WordPress site in a way that consumes the WordPress REST API and caches it as GraphQL for use in a React-powered Gatsby site. It has been downloaded 59k times this month and 851k times overall, as I write. That’s a healthy chunk of usage for one particular site-building technology. Literally, every use of gatsby-source-wordpress is using WordPress headlessly—that’s just what it is/does. If you’re interested in this, here’s Ganesh Dahal digging deep into it.

And that’s just one thing, it doesn’t factor in entire companies and products dedicated to the idea.

What is going headless and improve to?

The Gatsby integration makes a solid case for why anyone would consider a headless WordPress site. I’ll get to that.

Many advocate the reason is architectural. It de-couples the back end from the front end. It tears down the monolith. As a de-coupled system, the back and front ends can evolve independently. And yet, I’m less hot on that idea as years go by. For example, I’d argue that the chances of simply ripping out WordPress and replace it with another CMS in a headless setup like this is easier said than done. Also, the idea that I’m going to use the WordPress API not just to power a website, but also a native reading app, and some digital internet-connected highway billboard or something is not a use case that’s exploding in popularity as far as I can tell.

The real reason I think people reach for a WordPress back end for a Gatsby-driven front end is essentially this: they like React. They like building things from components. They like the fast page transitions. They like being able to host things somewhere Jamstack-y with all the nice developer previews and such. They like the hot module reloading. They like Prettier and JSX. They just like it, and I don’t blame them. When you enjoy that kind of developer experience, going back to authoring PHP templates where it takes manually refreshing the browser and maintaining some kind of hand-rolled build process isn’t exactly enticing.

Frontity is another product looking to hone in on React + WordPress. Geoff and Sarah shared how to do all this last year on the Vue/Nuxt side.

But will headless WordPress become more popular than the traditional theming model of WordPress that’s based on PHP templates that align to an explicit structure? Nah. Well, maybe it would if WordPress itself champions the idea and offers guidance, training, and documentation that make it easier for developers to adopt that approach. I’d buy into it if WordPress says that a headless architecture is the new course of direction. But none of those things are true. Consequently, to some degree, it’s a niche thing.

Just how niche is headless?

WP Engine is a big WordPress host and has a whole thing called Atlas. And that effort definitely looks like they are taking this niche market seriously. I’m not 100% sure what Atlas all is, but it looks like a dashboard for spinning up sites with some interesting looking code-as-config. One of the elephants in the room with headless WordPress is that, well, now you have two websites to deal with. You have wherever you are hosting and running WordPress, and wherever you are hosting and running the site that consumes the WordPress APIs. Maybe this brings those two things together somehow. The deploy-from-Git-commits thing is appealing and what I’d consider table stakes for modern hosting these days.

Another reason people are into headless WordPress is that the end result can be static, as in, pre-generated HTML pages. That means the server for your website can be highly CDN-ized, as it’s literally only static assets that are instantly available to download. There’s no PHP or database for server-side rendering things, which can be slow (and, to be fair, dealt with) since it adds a process ahead of rendering.

What’s “the WordPress way” for going headless?

I’d lump any service that builds a static version of your WordPress site into the headless WordPress bucket. That’s because, ultimately, those sites are using WordPress APIs to build those static files, just like Gatsby or whatever else would do.

That’s what Strattic does. They spin up a WordPress site for you that they consider staging. You do your WordPress work there, then use their publish system to push a static version of your site to production. That’s compelling because it solves for something that other headless WordPress usage doesn’t: just doing things the WordPress way.

For example, custom WordPress blocks or plugins might produce output that not only contains custom HTML, but CSS and JavaScript as well. Imagine a “carousel” block or plugin. That carousel isn’t going to work if all you’re doing is grabbing the post content from an API and dunking it onto a page. You’ll either need to go extract the CSS and JavaScript from elsewhere and include it, or somehow just know that isn’t how you do things anymore. You might attach the images as metadata somehow, pull them client-side, and do your own implementation of a carousel. With Strattic, theoretically, it’ll work as the HTML, CSS, and JavaScript is still present on the static site. But notably, you don’t have PHP, so Strattic had to hand-build form integrations, they use client-side Algolia for search, Disqus for comments, etc., because there is no server-side language available.

Shifter is another player here. It’s similar to Strattic where you work on your site in the WordPress admin, then publish to a static site. I believe Shifter even spins your WordPress site down when it’s not in use, which makes sense since the output is static and there is no reason a server with PHP and MySQL needs to be running. As an alternative, Shifter has a headless-only WordPress setup that presumably stays spun up all the time for outside API usage.

It’s fun to think about all this stuff

But as I do, I realize that the ideas and discussions around headless WordPress are mostly focused on the developer. WordPress has this huge market of people who just are not developers. Yet, they administer a WordPress site, taking advantage of the plugin and theme ecosystem. That’s kinda cool, and it’s impressive that WordPress serves both markets so well. There’s just a heck of a lot more WordPress site owners who aren’t developers than those who are, I reckon, so that alone will keep headless WordPress from being anything more than a relatively niche concept for some time. But, ya know, if they wanna put GraphQL in core, I’ll still take it kthxbye.


The post Just How Niche is Headless WordPress? appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Using New Gatsby Source WordPress Plugin

In my previous article, I discussed how I learned to create a decoupled WordPress powered Gatsby site using the Gatsby Source WPGraphQL plugin. The project was done following the ongoing developmental version of WPGraphQL and an excellent tutorial by Henrik Wirth. Although WPGraphQL was used in some production sites at that time, there were lot of iterations that introduced breaking changes. Since the release of WPGraphQL v1.0 last November, the plugin is stable and available via the WordPress plugin directory.

The WPGraphQL plugin can be used to create a site that uses WordPress for content management, but with a front-end that’s driven by Gatsby. We call this a “decoupled” or “headless” CMS because the site’s back-end and front-end are separate entities that still talk to one another via APIs where components on the front end consume data from the CMS.

The WPGraphQL plugin site has solid step-by-step documentation for getting started, and the release announcement post lists nine examples of production-level sites using the plugin.

Selected screenshots of production level decoupled WordPress sites with WPGraphQL.
The Denver Post, The Twin Cities Pioneer Press, The San Jose Mercury News, and Credit Karma have a decoupled WordPress site with WPGraphQL.

In the true sense of a “decoupled” or “headless” site, WPGraphQL can be used to port WordPress data to other frameworks, like Next.js, Vue.js, among others. For the Gatsby framework, the Gatsby Source WordPress plugin is recommended, and it utilizes WPGraphQL to source data from WordPress.

Let’s set everything up together and tour the plugin.

Prerequisites

In my previous article, we covered the prerequisites needed for setting up WordPress and Gatsby sites, and porting back-end WordPress data to a Gatsby-powered front-end site with site deployment. I’m skipping a lot of those details here because the fundamental concepts are the same for this article, except that WordPress data is fetched by the Gatsby Source WordPress plugin this time.

If you are new to Gatsby and just now jumping into Gatsby’s generated static site generator bandwagon, I’d suggest reading “An Honest Review of Gatsby” by React expert David Cramer and “Gatsby vs Next.js” by Jared Palmer. What we’re going to cover isn‘t for everyone, and these articles may be helpful to evaluate for yourself whether it’s the right technology for you and your project.

WPGraphQL, or GraphQL is the primary query language API used in Gatsby’s framework. There are frequent updates in GraphQL and that often requires expert knowledge and keeping an eye out for breaking changes. After all, GraphQL is designed by React experts for other React experts. That said, there’s some troubleshooting instructions and a WPGraphQL Slack where both the WPGraphQL and Gatsby Source WordPress plugin authors actively participate and help answer questions.

This article is not a step-by-step guide on how to use Gatsby Source WordPress Plugin. Again, that’s already available in Gatsby’s documentation. Conversely, if you happen to be an expert in React, JavaScript, Node.js or GraphQL, then what we cover here is probably stuff you already know. This article is an opinion piece based on my personal experience, which I hope is useful for the average WordPress user with basic working knowledge on the subject.

And, before we get started, it’s worth mentioning that the Gatsby Source WordPress plugin was completely rewritten in version 4 and uses WPGraphQL as its data source. The previous release, version 3, was built with REST API as its data source. Since the stable version of the plugin was recently released, the number of starter themes and demos that support it are limited.

First, we need WordPress

For this project, I set up a fresh WordPress site with Local by Flywheel that uses the default Twenty Twenty theme. I imported theme unit test data for pages and posts, as described in the WordPress Codex. While this was the baseline I was working with, this could have just as easily been an existing WordPress site that’s either on a remote server or a local install.

Now that we have an established baseline, we can log into the WordPress admin and install the WPGraphQL and WPGatsby plugins we need and activate them.

As we covered in the previous article, what this does is expose GraphQL and WPGraphiQL API in the WordPress admin, allowing the GraphiQL API to create a “playground” for testing GraphQL queries based on WordPress data.

Screenshot of the GraphiQL UI in the WordPress admin, showing a three-panel UI.
The GraphiQL screen provides three panels: one to navigate between different objects (left), one to query data (center), and one to visualize the returned data (right).

Now we need a Gatsby front-end

Gatsby is well known for good documentation and solid starter templates. To create a new WordPress-powered site, Gatsby tutorials suggest that either using a starter or starting from scratch is just fine for what we’re doing.

Gatsby also offers a library of example websites for basic use cases that are built around a specific technology. There currently happens to be one that uses WordPress and one that uses WordPress with the Advanced Custom Fields plugin. Note that the example sites in the library still use gatsby-source-wordpress plugin 3 and have not yet updated to the version 4, as of this writing.

According to Gatsby tutorials, there are three options for creating a WordPress-powered Gatsby site. Let’s look at each one.

Option 1: Using the Gatsby starter

The docs have a step-by-step guide on how to set up a WordPress-Gatsby site, but here’s the gist.

Run the following in the command line to fetch the starter from GitHub repository and clone it into a my-wpstarter project folder:

#! clone starter repo
gatsby new my-wpstarter https://github.com/gatsbyjs/gatsby-starter-wordpress-blog 

Then, install the npm packages

#! npm
npm install

#! or yarn
yarn install 

Now that the starter is cloned, let’s open the gatsby-config.js file in our code editor and update its URL option to fetch data from our WordPress endpoint (see above).

// gatsby-config.js
{
  resolve: gatsby-source-wordpress,
    options: {
     // WordPress is the GraphQL url.
     url: process.env.WPGRAPHQL_URL || https://wpgatsbydemo.wpengine.com/graphql,
  },
},

Now, we’ll replace the starter’s data source endpoint URL with our own WordPress site URL:

// gatsby-config.js file
{
  resolve: `gatsby-source-wordpress`,
  options: {
    url: `http://gatsbywpv4.local/graphql`,
  },
},

Let’s make sure we are in the my-wpstarter project directory. From the project folder, we’ll run the gatsby develop command to build our new Gatsby site from our WordPress data source endpoint. In the terminal we should be able see the gatsby-source-wordpress plugin fetching data, including errors and successful site processes along the way.

If we see a success Building development bundle message at the end, that means the Gatsby site build process is complete and the site can be viewed at http://localhost:8000.

The homepage of our starting site, displaying posts pulled from WordPress data in a single column.

This is a bare-bone starter blog with basic files and a few components. It’s file structure is very similar to the gatsby-starter-blog, except this one has a templates folder that includes blog-post.js and blog-post-achive.js template files.

When we view the GraphiQL API explorer at http://localhost:8000/___graphql we can see all of the data from WordPress exposed by WPGraphQL, as well as query and retrieve specific data right from the UI.

The GraphiQL UI showing three panels, one for the Explorer, one for the GraphiQL query, and one that displays the returned data from the query.
This example shows a query for menu items in WordPress (middle panel) and the returned data of that query (right panel).

You got it! Gatsby assumes the rest is up to us to build, using Gatsby components that pull in WordPress data for the presentation.

Option 2: Building from scratch

Gatsby’s documentation offers a detailed step-by-step guide on how to create a new WordPress-Gatsby site from scratch using Gatsby’s default starter theme.

We’ll spin up a new project from the command line:

#! create a new Gatsby site
gatsby new wpgatsby-from-scratch-demo

This gets us a wpgatsby-from-scratch-demo folder that includes the starter theme. From here, we’ll cd into that folder and start developing:

cd wpgatsby-from-scratch-demo
gatsby develop

Now we can open up http://localhost:8000 in the browser and get the welcome page.

Now we are good to go to get start grabbing data from our WordPress site. Let’s install the Gatsby Source Plugin:

#! install with rpm
npm install gatsby-source-wordpress

#! install with yarn
yarn add Gatsby-source-wordpress

If we check our browser now, you’ll noticed that nothing happens — we still get the same Gatsby welcome. To fetch our WordPress site data, we need to add the plugin to the gatsby-config.js file. Open the file and insert the following:

// gatsby-config.js
module.exports = {
  siteMetadata: {
    // ...
  },
  plugins: [
  // Add Gatsby-source-wordpress plugin
  {
      resolve: `gatsby-source-wordpress`,
      options: {
        /*
         * The full URL of the WordPress site's GraphQL API.
         * Example : 'https://www.example-site.com/graphql'
         */
        url: `http://gatsbywpv4.local/graphql`,
       },
     },
    // The following plugins are not required for gatsby-source-wordpress ....
  ],
}

Just like last time, we need to change the WordPress data endpoint source to the URL of our WordPress site. Let’s run gatsby develop in our terminal to start things up.

Two terminal windows, side-by-side. They are dark with light text.
Now we see that the createPages function is running successfully to build a development bundle (left), and that WordPress data for posts, pages, taxonomies, users, menus, and everything else are fetched (right).

However, when we open http://localhost:8000 in our browser, nothing seems to happen. We still see the same welcome screen. But if we examine GraphiQL in our browser (at http://localhost:8000/___graphql) then we see all WordPress data exposed to our Gatsby site that we can query and display as we want.

The three-panel GraphiQL UI.
GraphiQL shows that WordPress data is indeed exposed and we are able to create and execute queries.

Let’s test the following query I pulled straight from Gatsby’s tutorial, in the GraphiQL explorer:

query {
  allWpPost {
    nodes {
      id
      title
      excerpt
      slug
      date(formatString: "MMMM DD, YYYY")
    }
  }
}

When we run the above query, we will see the allWpPost.nodes property value, with sub properties for id, title, excerpt, and others.

Now, let’s open our src/components/pages/index.js component file and replace the code with this:

// src/components/pages/index.js
import  React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"

export default function Home({ data }) {
  return (
    <Layout>
      <SEO title="home" />
      <h1>My WordPress Blog</h1>
      <h4>Posts</h4>
      {data.allWpPost.nodes.map(node => (
        <div>
          <p>{node.title}</p>
          <div dangerouslySetInnerHTML={{ __html: node.excerpt }} />
        </div>
      ))}
    </Layout>
  )
}

export const pageQuery = graphql`
  query {
    allWpPost(sort: { fields: [date] }) {
      nodes {
        title
        excerpt
        slug
      }
    }
  }
`

Save it, restart the server with gatsby develop, and refresh the page. If the build was successful, then our site’s homepage should display a list of sorted blog posts from WordPress!

Following the tutorial, let’s create pages for each blog post and link the post title from the list to the post page. The process of creating pages using Markdown data is described in detail in Part 7 of the Gatsby’s foundational tutorial, which we will follow here as well.

As described in the tutorial, Gatsby uses createPages API, or what it calls as its “workhorse” API, to programmatically create pages from data (from Markdown or WordPress). Unlike Markdown data, we don’t need to create a slug here because each WordPress post has its own unique slug which can be fetched from the WordPress data endpoint.

Creating pages for each post

Gatsby uses the gatsby-node.js file, located at the root of our project, to programmatically create blog post. Let’s open the gatsby-node.js file in our text editor add the following code from the tutorial.

// gatsby-node.js 
const path = require(`path`)

exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions
  return graphql(`
    {
      allWpPost(sort: { fields: [date] }) {
        nodes {
          title
          excerpt
          content
          slug
        }
      }
    }
  `).then(result => {
    console.log(JSON.stringify(result, null, 4))
    process.exit()
  })
}

As noted in the Gatsby Part 7 tutorial, the above code is the first part of creating our post pages from WordPress data source. Following the guide, let’s restart our server and develop our site with gatsby develop.

We should see console.log output in our terminal as pages being build). However, our homepage still looks the same. To create single posts, Gatsby requires templates to build pages, which we will create in next step.. That’s what we’ll do next.

Creating blog post templates

Let’s create a src/components/templates folder in the src/ directory and create a blog-post.js file by pasting the following code snippets from the tutorial:

// src/templates/blog-post.js
import React from "react"
import Layout from "../components/layout"
import { graphql } from "gatsby"

export default function BlogPost({ data }) {
  const post = data.allWpPost.nodes[0]
  console.log(post)
  return (
    <Layout>
      <div>
        <h1>{post.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.content }} />
      </div>
    </Layout>
  )
}
export const query = graphql`
  query($slug: String!) {
    allWpPost(filter: { slug: { eq: $slug } }) {
      nodes {
        title
        content
      }
    }
  }
`

As explained in the tutorial, the above code snippets create a single post with React JSX and wraps post.title and post.content (lines 12-13) around the src/components/layout.js components. At the bottom section of the file, a GraphQL query is added and calls a specific post based on the post slug variable $slug. This variable is passed to the blog-post.js template when the page is created in gatsby-node.js.

Next we should also update lines 12-13 of our gatsby-node.js file with the following code from the tutorial.

// gatsby-node.js
const path = require(`path`)

 exports.createPages = ({ graphql, actions }) => {
   const { createPage } = actions
   return graphql(`
     {
       allWpPost(sort: { fields: [date], order:DEC }) {
         nodes {
           title
           excerpt
           content
           slug
         }
       }
     }
   `).then(result => {
    result.data.allWpPost.nodes.forEach(node => {
        createPage({
          path: node.slug,
          component: path.resolve(`./src/templates/blog-post.js`),
          context: {
            // This is the $slug variable passed to blog-post.js
            slug: node.slug,
          },
        })
      })
   })
 }

Let‘s stop and restart our local server with gatsby develop and view the site. We won’t see our homepage with a list of blog post links. However, if we check with http://localhost:8000/abcdf we should see the following 404 page with a list of individual pages and posts links.

If we check http://localhost:8000/hello-gatsby-world, we should our “Hello Gatsby WordPress World” post in all its glory.

The next step is to link the post titles from the homepage to the actual posts.

Linking to posts from the homepage

Linking the work from the homepage to post pages is done by wrapping post titles in the index.js file with Gatsby‘s Link component. Let’s open the index.js file that we created earlier and add the Link component:

// src/components/pages/index.js
import React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"

export default function Home({ data }) {
  return (
    <Layout>
      <SEO title="home" />
     {/* <h1>My WordPress Blog</h1>
      <h4>Posts</h4> */}
      {data.allWpPost.nodes.map(node => (
        <div key={node.slug}>
          <Link to={node.slug}>
            <h2>{node.title}</h2>
          </Link>
          <div dangerouslySetInnerHTML={{ __html: node.excerpt }} />
        </div>
      ))}
    </Layout>
  )
}

export const pageQuery = graphql`
  query {
    allWpPost(sort: { fields: [date], order: DEC  }) {
      nodes {
        title
        excerpt
        slug
      }
    }
  }
`

We imported the Link component from Gatsby and then wrapped the post title with the Link component and reference the slug of the post. Let’s clean up the code by commenting out the page title, changing the title element to <h2>, and adding sorted posts order to DEC in our graphql query as well as the gatsby-node.js file.

As we did earlier, let’s stop and restart the development server with gatsby develop, and view our homepage at http://localhost:8000. The post title should link to single post page.

This is as far as we’re going to take this second method. The rest of what we cover will describe how to fetch menu items and query other data types — like custom post types — and configure incremental build and previews etc.

You can apply the same procedure to calling and creating pages, custom post types, custom fields, taxonomies, and all the fun and flexible content WordPress is known for. This can be as simple or as complex as you would like it to be, so explore and have fun with it!

Gatsby tutorial doc 

Option 3: Using Gatsby’s WordPress Twenty Twenty Starter

Gatsby’s starter template for the default WordPress Twenty Twenty theme is created and maintained by Henrik Wirth, who also has an extremely detailed and thorough step-by-step guide that you might recall from my previous article. This starter, unlike the others, is actually updated to version 4 of the Gatsby Source Plugin and works out of the box after the initial WordPress setup described in the documentation. It maintains the same Twenty Twenty styling in the Gatsby front-end site, but has few limitations — including, comments, monthly archive pages, and tags — that are unsupported.

First let’s clone the starter in our twenty-twenty-starter folder.

#! clone gatsby-starter-wordpress-twenty-twenty 
gatsby new twenty-twenty-starter https://github.com/henrikwirth/gatsby-starter-wordpress-twenty-twenty

Let’s cd into that folder and then run gatsby develop to spin up the site. It won’t work properly the first time because we have not changed our WPGRAPHQL_URL value yet in the env.example file. We need to rename the file from .env.example to simply .env, as suggested in the documentation.

After that, restart the development server with gatsby develop. It should build the site successfully.

The menu may or may not appear depending on how the WordPress menu is named. The starter’s menu slug for querying menu items is primary in Menu.js (line 8). Because I had set my WordPress site up using main-menu instead, I had to update the Menu.js file accordingly.

Screenshot showing Menu.js file with changed menu slug to “main-menu” in line 8.

Because the starter was tested with older versions of our tools , I decided bump up the plugins  to the latest versions — WPGraphQL 1.2.6, WPGatsby 1.0.6, and Gatsby Source WordPress  4.0.1 — and it worked fine without any errors.

The Twenty Twenty starter follows the file structure of the Twenty Nineteen Gatsby theme, as well as Gatsby Starter WordPress Advanced. Henrik Wirth describes how WordPress data is ported to Gatsby in his step-by-step guide, as does Muhammad Muhsin in a tutorial. Otherwise, creating pages, page templates, porting menu items is exactly the same.

Screenshot showing Gatsby Starter WordPress Twenty Twenty’s file structure.

This starter uses the same CSS that the default WordPress Twenty Twenty theme does, and the same assets folder, including fonts, images, SVG files, and other files that are included in the default theme.

Screenshot showing the Gatsby Starter WordPress Twenty Twenty assets folder contents open in VS Code.

If you are happy with WordPress Twenty Twenty styling, then that’s it. Enjoy your new decoupled Gatsby site!

But let’s say we want to work with custom styles. The CSS files are imported from the assets folder via the gatsby-browser.js file.

Screenshot showing the Gatsby StarterWordPress Twenty Twenty style.css file opened next to the WordPress Twenty Twenty theme’s style.css file. The two contain the exact same code.

Let’s modify the styles for the site’s header, footer, posts and pages. Gatsby provides different options to style its components and, in this project, I followed the CSS module for styling and modified CSS markup of the Twenty Twenty starter components accordingly.

We can start by creating a style folder at src/components/styles and, inside it, a base folder. Here’s the general file structure we’re aiming for:

#! partial structure of /style folder
src
 |--/components
   |--/styles
     |--main.css          
     |--/base
       |--reset.css
       |--variables.css
     |--/scss
       |--header.module.css
       |--mainNav.module.css
       |--footer.module.css
       |--elements.module.css
       // and so on...

We want to style the site’s header and footer, so let’s open up the Header.js and Footer.js components in the starter and replace the code with the following:

// src/components/Header.js
import React from "react"
import { graphql, Link, useStaticQuery } from "gatsby"
import Menu from "./menu"
import style from "../styles/scss/header.module.css"
import logo from '../images/gatsby-icon.png'

const Header = ( ) => {
  const { wp } = useStaticQuery(graphql`
    {
      wp {
        generalSettings {
          title
          description
        }
      }
    }
  `)
  return (
    <header className={style.masthead}>
      <div className={style.masthead_info}>

      <Link to="/">
        <img src={logo} alt="logo" width="100" height="100" display="inline-block" marginBottom= "0"  className={style.site_logo} />
      </Link>
      <div className={style.site_header} >
        <div className={style.site_title}>
          <Link
            to="/"
            dangerouslySetInnerHTML={{ __html: wp.generalSettings.title }} />
        </div>
        <div className={style.site_description} dangerouslySetInnerHTML={{ __html: wp.generalSettings.description }} /></div>

      </div>
      <Menu />
    </header>
  )
}

export default Header

Similarly, the Footer.js component was modified as follows:

// src/components/Footer.js
import React from "react"

import style from "../styles/scss/footer.module.css"

export default () => (
  <footer className={style.colophon}>
    <p>© {new Date().getFullYear()} | This site is Powered by {'   ' } <a href="https://www.gatsbyjs.org">GatsbyJS</a> {'   and  '} <a href="https://www.wordpress.org">WordPress</a></p>
  </footer>
)

Now, let’s restart our development server. We should see the following, including a new customized header and footer. I used the same style from Learning Gatsby which is an online course by Morten Rand-Hendriksen (I am a fan!).

Screenshot showing modified header and footer styling.
Screenshot showing modified header and footer styling.

You can grab the all the code I used over at GitHub.

What all this means for WordPress enthusiasts

There are many posts that compare the advantages and disadvantages of a decoupled WordPress and Jamstack site like the Gatsby examples we’ve covered. In my research, I realized that none of them are as exhaustive as what Chris already wrote in ”WordPress and Jamstack” where he compares everything, from performance and features, to the developer experience and build processes, and beyond.

I found the following articles draw some helpful conclusions on a variety of topics, including:

What’s the cost?

The general assumption is that Jamstack hosting is cheap, and cheaper than traditional LAMP stack hosting. But there’s actually quite a bit to consider and your actual costs might vary.

  • “How to Run Your WordPress Site On Local, Gatsby and Netlify for FREE!” (Nate Fitch): Nate’s take is that a headless WordPress setup like this might be a good option if the project is a static blog or a site that doesn’t require any interactions. For example, It wouldn’t take too much work to get images hosted on Cloudinary, or another CDN, but it would for large, interactive sites.
  • “WordPress and Jamstack” (Chris Coyier): There’s a specific section in here where Chris breaks down the pricing for different types of hosting for Jamstack sites and why a blanket statement like “Jamstack is cheaper” doesn’t fly because the actual cost depends on the site and its usage.
  • “Choosing between Netlify, Vercel and Digital Ocean” by (Zell Liew): Zell discusses his experience choosing a hosting plan. His take: If you have a small project, go with Netlify; if you have a larger project, use Digital Ocean.

Why go static at all?

Considering all the things you get for “free” in WordPress — think comments, plugins, integrations, etc. — you might wonder if it’s even worth trading in a server-side setup for a client-side solution. In his “Static or Not?” post, Chris breaks down the reasons why you’d want to choose one over the other.

How do we get commenting functionality?

We get native commenting right out of the box with WordPress. Yet, support for comments on a static site is a bit of a juggernaut. In “JAMstack Comments” here on CSS-Tricks, the author explains how dynamic comments can be implemented in a static site, like Gatsby, using Netlify services. I briefly touched on this in my previous article.

What about SEO?

  • “Gatsby SEO For WpGraphQL and Yoast” (Gatsby Community Plugin): The widely used Yoast SEO plugin for WordPress can be integrated into a Gatsby front-end using this plugin.
  • “A primer on JavaScript SEO for WordPress” (Jono Alderson): This exhaustive guide includes a section on how to integrate Yoast SEO into a headless architecture and the implications of relying on JavaScript for SEO. The bottom line is that theme and plugin developers shouldn’t worry much about the changing landscape of JavaScript and SEO as long as they continue following best practices. At the same time, they should be aware of what’s changing and adapt accordingly.

How do things work together?

There are currently no Gatsby React templates that are geared toward non-developers but some agencies, like Gatsby WP Themes and the Themeforest marketplace, are beginning to fill the gap. For example, Gatsby WP Themes covers plugins for dynamic contents like MailChimp integration, using the Contact Form 7 plugin for forms, Yoast SEO, and more. Themeforest lists 30+ Gatsby templates, including the Gatsby – WordPress + eCommerce theme which gives you an idea of how far we can go with this sort of setup. Just remember: these are commercial sites, and much of what you’ll find has a cost attached to it.

My evolving personal take

If you recall, I ended my last article with a personal reflection on my journey to create a headless WordPress site that uses Gatsby as the front end. My initial take was less than a glowing review:

Based on my very limited experience, I think that currently available Gatsby WordPress themes are not ready for prime time use for users like me. Yeah, it is exciting to try something on the bleeding edge that’s clearly in the minds of many WordPress users and developers. At the same time, the constantly evolving work being done on the WordPress block editor, WPGraphQL and Gatsby Source WordPress plugins makes it difficult to predict where things are going and when it will settle into a state where it is safe to use in other contexts.

So, after all this my long journey to headless WordPress site, what is my take now? As an open-minded learner, my thoughts are still evolving. But I couldn’t agree more with what Chris says in his “Static or Not?” post:

It’s a perfectly acceptable and often smart choice to run a WordPress site. I think about it in terms of robustness and feature-readiness. Need e-commerce? It’s there. Need forms? There are great plugins. Need to augment how the CMS works? You have control over the types of content and what is in them. Need auth? That’s a core feature. Wish you had a great editing experience? Gutenberg is glorious.

I am a WordPress enthusiast and I love WordPress as a CMS. However, as a technological learning challenge, I have not given up yet to have a decoupled WordPress site as a personal project.

I must admit that learning to create a decoupled Gatsby site with WordPress has continued to be frustrating. I acknowledge that any modern technology stack is not “a cup of tea” for many WordPress users. Gatsby has steep learning curve as these stacks are targeted for experienced React and JavaScript developers.

Self-learning a new technology can be a frustrating experience. Learning Gatsby is especially frustrating if we (including yours truly) happen to lack experience with Node, React, JavaScript and, most importantly, GraphQL. My learning project sites would break because of some dependency and fixing it might take me several days of research. I sometimes wonder if the trouble is worth the outcome. Don’t get me wrong; my frustration is with my own lack of experience, not the frameworks themselves (because they are amazing).

Even experienced developers like David Cramer and Jared Palmer find using Gatsby and GraphQL frustrating and echo some of the same sentiments that we beginners face when using GraphQL. I couldn’t agree more with David who writes:

It’s a static website generator. It literally does not need GraphQL all over the place. While there are few instances in the real world where that is valuable, it shouldn’t require a GraphQL API to read objects that are already in memory.

GraphQL is an opinionated query language API and its specification changes frequently. Indeed, most of the discussion in the WPGraphQL Slack are related to queries.

While working on this project, I came cross the Frontity React Framework while reading an article on CSS-Tricks. It fetches all WordPress data with the REST API without writing a single query. That seems to be a better option, at least for my use case. Additionally, it appears to be a much simpler alternative. In my brief experience with it, I didn’t have to deal with any dependency or library issues at all. Frontity’s themes concept is so WordPress-y and provides excellent tutorials.

I am currently exploring whether the Frontity framework would be a better option for my decoupled project site and will share my experience in a future article.

Resources

Gatsby feels like it is targeted at experienced React and JavaScript developers, not for beginners like me! The gatsby-source-wordpress and gatsby-source-wpgraphql plugins do an excellent job of exposing WordPress data into Gatsby sites, but the rest is up to users to present the data on the front end using your framework of choice: React, Vue, Next, etc.

A lack of sound knowledge of React and JavaScript is the main hurdle for beginners. The Gatsby community fills a lot of these gaps, and there are a lot of resources available to keep learning and exploring.

Gatsby Conference 2021 talks

Two workshop talks from the recent 2021 Gatsby Conference were related to Gatsby WordPress sites. In one, Jason Bahl hosts a workshop that walks through how to create a Gatsby blog powered by WordPress data, including support the Yoast SEO plugin, and how to deploy the site to Gatsby Cloud.

There’s another workshop hosted by WP Engine’s Matt Landers where he demonstrates how to set things up using the Advanced Custom Fields plugin to create a team member page.

Both talks are good, especially if you learn better with hands-on experience. I also found this Matt Report podcast episode with Jason Bahl where Jason answers basic questions that are geared toward beginners.

Tutorial courses

Morten Rand-Hendriksen has an excellent course on LinkedIn Learning that uses the Gatsby Source WordPress plugin. If you are interested in more hands-on experience making a customized site that expands on the two Gatsby starters we covered, this course is great because in teaches how to create a complete working site, complete with a dropdown header navigation, footer menus, posts, pages, categories, tags, and page navigation.

Check that out, a homepage, post template, categories, tags, a header that includes navigation… there’s a lot going on here!

The exercise files for the course are available in the GitHub LinkedIn Learning repository.

Gatsby starters

At the time I’m writing this, there are ten Gatsby starters for WordPress. As we mentioned earlier, only Gatsby Starter WordPress Twenty Twenty is based on the latest version of the Gatsby Source WordPress plugin; the rest are version 3.


Thanks for reading. I am always interested to know how fellow WordPress users who lack heavy technical experience like me are using this plugin. If you have any feedback, please feel free to post them in the comments.


The post Using New Gatsby Source WordPress Plugin appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Reconciling Editor Experience and Developer Experience in the CMS

Components are great, aren’t they? They are these reusable sources of truth that you can use to build rock-solid front-ends without duplicating code.

You know what else is super cool? Headless content management! Headless content management system (CMS) products offer a content editing experience while freeing that content in the form of data that can be ported, well, to any API-consuming front-end UI. You can structure your content however you’d like (depending on the product), and pull that content into your front-end applications.

Using these two things together — a distributed CMS solution with component-based front-end applications — is a core tenet of the Jamstack.

But, while components and headless CMSs are great on their own, it can be difficult to get them to play nicely together. I‘m not saying it‘s difficult to hook one up to the other. In a lot of cases, it’s actually quite painless. But, to craft a system of components that is reusable and consistent, and to have that system maintain parity with a well-designed CMS experience is a difficult thing to achieve. It’s that win-win combo of being able to freely write content and then have that content structured into predictable components that makes headless content management so appealing.

Achieving parity between a CMS and front-end components

My favorite demonstrating this complexity is a simple component: a button. Let‘s say we’re working with React to build components and our button looks like this:

<Button to="/">Go Home</Button>

In the lovely land of React, that means the <Button> component has two props (i.e. properties, attributes, arguments, etc.) — to and children. children is a React thing that holds all the content within the opening and closing tags, which is “Go Home” in this case.)

If we’re going to enable users in the content editor to add buttons to the site, we want a system for them that makes it easy to understand how their actions in the CMS affect what appears on screen in the front-end app. But we also want our developer(s) to work productively with component properties that make sense to them and within the framework they’re working (i.e. React in our example).

How do we do that?

We could…

…use fields in the CMS that match the components’ properties, though I’ve had little success with this approach. to and children don‘t make much sense to content editors trying to build a button. Believe me, I‘ve tried. I‘ve tried with beginners and experienced editors alike. I‘ve tried helper text. It doesn’t matter. It’s confusing.

What makes more sense is using words editors are more likely to understand, like label or text for children and url for to.

Showing a mockup of CMS text input fields for a button component, one for a to field with https as a placeholder, and another for children with Buy Now as a placeholder.
😕
Showing a mockup of CMS text input  fields for a button component, one for a URL field with https as a placeholder, and another for Button Label with Buy Now as a placeholder.
🤓

But then we’d be out of sync with our code.

Or what if we…

masked attributes in the CMS. Most headless CMS solutions enable you to have a different value for the label of the field than the name that is used when delivering content via an API.

We could label our fields Label and URL, but use children and to as the names. We could. But we probably shouldn’t. Remember what Ian Malcolm said?

On the surface, masking attributes makes sense. It’s a separation of concerns. The editors see something that makes them happy and productive, and the developers work with the names that make sense to them. I like it, but only in theory. In practice, it confuses developers. Debugging a content editor issue often requires digging through extra layers (i.e. time) to find the relationship between labels and field names.

Or why not …

…change the properties. Wouldn’t it be easier for developers to be flexible? They’re the ones designing the system, after all.

Yes, that’s true. But if you follow that rule exclusively, it’s inevitable that you’re going to run into some issue along the way. You’ll likely end up fighting against the framework, or props will just feel goofy.

In our example, using label and url as props for a button works totally fine for data that originates from the CMS. But that also means that any time our developers want to use a button within the code, it looks like this:

<Button label="Go Home" url="/" />

That may seem okay on the surface, but it significantly limits the power of the button. Let’s say I want to support some other feature, like adding an icon within the label. I’m going to need some additional logic or another property for it. If I would have used React’s children approach instead, it would have just worked (likely after some custom styling support).

Okay, so… what do we do?

Introducing transformers

The best approach I’ve found is to separately optimize the editor and developer experiences. Craft a CMS experience that is catered to the editors. Build a codebase that is easy for developers to navigate, understand, and enhance.

The result is that the two experiences will not be in parity with one another. We need some set of utilities to transform the data from the CMS structure into something that can be used by the front-end, regardless of the framework and tooling you’re using.

I call these utilities transformers. (Aren’t I so good at naming things!?) Transformers are responsible for consuming data from your CMS and transforming it into a shape that can be easily consumed by your components.

Illustration showing a rounded square that says Data Source pointing to a yellow box that says transformer, pointing to another rounded square that says component. There is a small code snippet on both sides of the yellow square showing how it transforms the Label and URL fields to Children and To, respectively.

While I‘ve found that transforming data is the smoothest means to get great experiences in both the CMS and the codebase, I don‘t have an obvious solution for how (or perhaps where) those transformations should happen. I‘ve used three different approaches, all of which have their pros and cons. Let’s take a look at them.

1. Alongside components

One approach is to put transformers right alongside the components they are serving. This is the approach I typically take in organizing component-based projects — to keep related files close to one another.

The same illustrated diagram, but the yellow box is now the button index.js file that points to a transformer.js file that then points to a button component.js file.

That means that I often have a directory for every component with a predictable set of files. The index.js acts as the controller for the component. It is responsible for importing and exporting all other relevant files. That makes it trivial to wrap the component with some logic-based behavior. In other words, it could transform properties of the component before rendering it. Here’s what that might look like for our button example:

import React from "react"

import Component from "./component"
import transform from "./transformer"

const Button = props => <Component {...transform(props)} />

export default Button

The transform.js file might look like this:

export default input =&gt; {
  return {
    ...input,
    children: input.children || input.label,
    to: input.to || input.url
  }
}

In this example, if to and children were properties sent to the component, it works just fine! But if label and url were used instead, they are transformed to children and to. That means the <Button> component (component.js) only has to worry about using children and to.

const Button = ({ children, to }) => <a href={to}>{children}</a>

I personally love this approach. It keeps the logic tightly coupled with the component. The biggest downside I‘ve found thus far is that it’s a large number of files and transforms, when the entire dataset for any given page could be transformed earlier in the stack, which would be…

2. At the top of the funnel

The data has to be pulled into the application via some mechanism. Developers use this mechanism to retrieve as much data for the current page or view as possible. Often, the fewer number of queries/requests a page is required to make, the better its performance.

In other words, that mechanism often exists near the top of the funnel (or stack), as opposed to each component pulling its own data in dynamically. (When that’s necessary, I use adapters.)

Another illustration, this time where the yellow box is labeled import mechanism, and it has three arrows, each pointing to a white square, labeled, component 1, component 2, and component 3, respectively.

The mechanism that retrieves the page data could also be responsible for transforming all the data for the given page before it renders any of its components.

In theory, this is a better approach than the first one. It decreases the amount of work the browser has to do, which should improve the front-end performance. That means the server has to do more work, but that’s often a better choice.

In practice, though, this is a lot of work. Data structures can be big, complex, and interwoven. It can take a heck of a lot of work to transform everything into the right format at the top of the funnel, and then pass the transformed data down to components. It’s also more difficult to test because of the potential complexity and variation of the giant data blob retrieved at the top of the stack. With the first approach, testing the transformer logic for the button is trivial. With this approach, you’d want to account for transforming button data anywhere that it might appear in the retrieved data object.

But, if you can pull it off, this is generally the better approach.

3. The middleman engine

The third and final (and magical) approach is to do all this work somewhere else. In this case, we could build an engine (i.e. a small application) that would do the transformations for us, and then make the content available for the application to consume.

Another illustration, this time where the yellow box is the abstracted data source, which points to a white box labeled import mechanism, which then points to the same three white squares representing components that are outlined in the previous illustration.

This is likely even more work than the second approach. And it has added cost and maintenance in running an additional application, which takes more effort to ensure it is rock solid.

The major upside to this approach is that we could build this as an abstracted engine. In other words, any time we bring in data to any front-end application, it goes through this middleman engine. That means if we have two projects that use the same CMS or data source, our work is cut down significantly for the second project.


If you aren‘t doing any of this today and want to start, my advice is to treat these approaches like stepping stones. They grow in complexity and maintenance and power as the application grows. Start with the first approach and see how far that gets you. Then, if you feel like you could benefit from a jump to the second, do it! And if you’re feeling like living dangerously, go for the third!

In the end, what matters most is crafting an experience that both your editors and your developers understand and enjoy. If you can do that, you win!


The post Reconciling Editor Experience and Developer Experience in the CMS appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

JAMStack CMS: Why and How To Use It

Introduction

Has it recently crossed your mind why so many businesses failed to respond to COVID-inflicted challenges? After the 2020 turmoil, they’re hoping to break even at best while suffering from significant customer churn and technology inconsistencies. However, only trying to retain your existing customers is not the best idea for business growth.

That is why unprecedented times make businesses start looking for nontrivial solutions to reach wider audiences. As customers are getting more mature in their digital-driven journey, companies have a harder time meeting the customer of today’s expectations. Given that face-to-face communication is not an option these days, the only medium for successful B2B/B2C interaction is your website content.
Static site generators adoption graph

Rendering the WordPress philosophy in GraphQL

WordPress is a CMS that’s coded in PHP. But, even though PHP is the foundation, WordPress also holds a philosophy where user needs are prioritized over developer convenience. That philosophy establishes an implicit contract between the developers building WordPress themes and plugins, and the user managing a WordPress site.

GraphQL is an interface that retrieves data from—and can submit data to—the server. A GraphQL server can have its own opinionatedness in how it implements the GraphQL spec, as to prioritize some certain behavior over another.

Can the WordPress philosophy that depends on server-side architecture co-exist with a JavaScript-based query language that passes data via an API?

Let’s pick that question apart, and explain how the GraphQL API WordPress plugin I authored establishes a bridge between the two architectures.

You may be aware of WPGraphQL. The plugin GraphQL API for WordPress (or “GraphQL API” from now on) is a different GraphQL server for WordPress, with different features.

Reconciling the WordPress philosophy within the GraphQL service

This table contains the expected behavior of a WordPress application or plugin, and how it can be interpreted by a GraphQL service running on WordPress:

CategoryWordPress app expected behaviorInterpretation for GraphQL service running on WordPress
Accessing dataDemocratizing publishing: Any user (irrespective of having technical skills or not) must be able to use the softwareDemocratizing data access and publishing: Any user (irrespective of having technical skills or not) must be able to visualize and modify the GraphQL schema, and execute a GraphQL query
ExtensibilityThe application must be extensible through pluginsThe GraphQL schema must be extensible through plugins
Dynamic behaviorThe behavior of the application can be modified through hooksThe results from resolving a query can be modified through directives
LocalizationThe application must be localized, to be used by people from any region, speaking any languageThe GraphQL schema must be localized, to be used by people from any region, speaking any language
User interfacesInstalling and operating functionality must be done through a user interface, resorting to code as little as possibleAdding new entities (types, fields, directives) to the GraphQL schema, configuring them, executing queries, and defining permissions to access the service must be done through a user interface, resorting to code as little as possible
Access controlAccess to functionalities can be granted through user roles and permissionsAccess to the GraphQL schema can be granted through user roles and permissions
Preventing conflictsDevelopers do not know in advance who will use their plugins, or what configuration/environment those sites will run, meaning the plugin must be prepared for conflicts (such as having two plugins define the SMTP service), and attempt to prevent them, as much as possibleDevelopers do not know in advance who will access and modify the GraphQL schema, or what configuration/environment those sites will run, meaning the plugin must be prepared for conflicts (such as having two plugins with the same name for a type in the GraphQL schema), and attempt to prevent them, as much as possible

Let’s see how the GraphQL API carries out these ideas.

Accessing data

Similar to REST, a GraphQL service must be coded through PHP functions. Who will do this, and how?

Altering the GraphQL schema through code

The GraphQL schema includes types, fields and directives. These are dealt with through resolvers, which are pieces of PHP code. Who should create these resolvers?

The best strategy is for the GraphQL API to already satisfy the basic GraphQL schema with all known entities in WordPress (including posts, users, comments, categories, and tags), and make it simple to introduce new resolvers, for instance for Custom Post Types (CPTs).

This is how the user entity is already provided by the plugin. The User type is provided through this code:

class UserTypeResolver extends AbstractTypeResolver
{
  public function getTypeName(): string
  {
    return 'User';
  }

  public function getSchemaTypeDescription(): ?string
  {
    return __('Representation of a user', 'users');
  }

  public function getID(object $user)
  {
    return $user->ID;
  }

  public function getTypeDataLoaderClass(): string
  {
    return UserTypeDataLoader::class;
  }
}

The type resolver does not directly load the objects from the database, but instead delegates this task to a TypeDataLoader object (in the example above, from UserTypeDataLoader). This decoupling is to follow the SOLID principles, providing different entities to tackle different responsibilities, as to make the code maintainable, extensible and understandable.

Adding username, email and url fields to the User type is done via a FieldResolver object:

class UserFieldResolver extends AbstractDBDataFieldResolver
{
  public static function getClassesToAttachTo(): array
  {
    return [
      UserTypeResolver::class,
    ];
  }

  public static function getFieldNamesToResolve(): array
  {
    return [
      'username',
      'email',
      'url',
    ];
  }

  public function getSchemaFieldDescription(
    TypeResolverInterface $typeResolver,
    string $fieldName
  ): ?string {
    $descriptions = [
      'username' => __("User's username handle", "graphql-api"),
      'email' => __("User's email", "graphql-api"),
      'url' => __("URL of the user's profile in the website", "graphql-api"),
    ];
    return $descriptions[$fieldName];
  }

  public function getSchemaFieldType(
    TypeResolverInterface $typeResolver,
    string $fieldName
  ): ?string {
    $types = [
      'username' => SchemaDefinition::TYPE_STRING,
      'email' => SchemaDefinition::TYPE_EMAIL,
      'url' => SchemaDefinition::TYPE_URL,
    ];
    return $types[$fieldName];
  }

  public function resolveValue(
    TypeResolverInterface $typeResolver,
    object $user,
    string $fieldName,
    array $fieldArgs = []
  ) {
    switch ($fieldName) {
      case 'username':
        return $user->user_login;

      case 'email':
        return $user->user_email;

      case 'url':
        return get_author_posts_url($user->ID);
    }

    return null;
  }
}

As it can be observed, the definition of a field for the GraphQL schema, and its resolution, has been split into a multitude of functions:

  • getSchemaFieldDescription
  • getSchemaFieldType
  • resolveValue

Other functions include:

This code is more legible than if all functionality is satisfied through a single function, or through a configuration array, thus making it easier to implement and maintain the resolvers.

Retrieving plugin or custom CPT data

What happens when a plugin has not integrated its data to the GraphQL schema by creating new type and field resolvers? Could the user then query data from this plugin through GraphQL?

For instance, let’s say that WooCommerce has a CPT for products, but it does not introduce the corresponding Product type to the GraphQL schema. Is it possible to retrieve the product data?

Concerning CPT entities, their data can be fetched via type GenericCustomPost, which acts as a kind of wildcard, to encompass any custom post type installed in the site. The records are retrieved by querying Root.genericCustomPosts(customPostTypes: [cpt1, cpt2, ...]) (in this notation for fields, Root is the type, and genericCustomPosts is the field).

Then, to fetch the product data, corresponding to CPT with name "wc_product", we execute this query:

{
  genericCustomPosts(customPostTypes: "[wc_product]") {
    id
    title
    url
    date
  }
}

However, all the available fields are only those ones present in every CPT entity: title, url, date, etc. If the CPT for a product has data for price, a corresponding field price is not available. wc_product refers to a CPT created by the WooCommerce plugin, so for that, either the WooCommerce or the website’s developers will have to implement the Product type, and define its own custom fields.

CPTs are often used to manage private data, which must not be exposed through the API. For this reason, the GraphQL API initially only exposes the Page type, and requires defining which other CPTs can have their data publicly queried:

The plugin provides an interface for whitelisting CPTs to be exposed in the API.

Transitioning from REST to GraphQL via persisted queries

While GraphQL is provided as a plugin, WordPress has built-in support for REST, through the WP REST API. In some circumstances, developers working with the WP REST API may find it problematic to transition to GraphQL.

For instance, consider these differences:

  • A REST endpoint has its own URL, and can be queried via GET, while GraphQL, normally operates through a single endpoint, queried via POST only
  • The REST endpoint can be cached on the server-side (when queried via GET), while the GraphQL endpoint normally cannot

As a consequence, REST provides better out-of-the-box support for caching, making the application more performant and reducing the load on the server. GraphQL, instead, places more emphasis in caching on the client-side, as supported by the Apollo client.

After switching from REST to GraphQL, will the developer need to re-architect the application on the client-side, introducing the Apollo client just to introduce a layer of caching? That would be regrettable.

The “persisted queries” feature provides a solution for this situation. Persisted queries combine REST and GraphQL together, allowing us to:

  • create queries using GraphQL, and
  • publish the queries on their own URL, similar to REST endpoints.

The persisted query endpoint has the same behavior as a REST endpoint: it can be accessed via GET, and it can be cached server-side. But it was created using the GraphQL syntax, and the exposed data has no under/over fetching.

Extensibility

The architecture of the GraphQL API will define how easy it is to add our own extensions.

Decoupling type and field resolvers

The GraphQL API uses the Publish-subscribe pattern to have fields be “subscribed” to types.

Reappraising the field resolver from earlier on:

class UserFieldResolver extends AbstractDBDataFieldResolver
{
  public static function getClassesToAttachTo(): array
  {
    return [UserTypeResolver::class];
  }

  public static function getFieldNamesToResolve(): array
  {
    return [
      'username',
      'email',
      'url',
    ];
  }
}

The User type does not know in advance which fields it will satisfy, but these (username, email and url) are instead injected to the type by the field resolver.

This way, the GraphQL schema becomes easily extensible. By simply adding a field resolver, any plugin can add new fields to an existing type (such as WooCommerce adding a field for User.shippingAddress), or override how a field is resolved (such as redefining User.url to return the user’s website instead).

Code-first approach

Plugins must be able to extend the GraphQL schema. For instance, they could make available a new Product type, add an additional coauthors field on the Post type, provide a @sendEmail directive, or anything else.

To achieve this, the GraphQL API follows a code-first approach, in which the schema is generated from PHP code, on runtime.

The alternative approach, called SDL-first (Schema Definition Language), requires the schema be provided in advance, for instance, through some .gql file.

The main difference between these two approaches is that, in the code-first approach, the GraphQL schema is dynamic, adaptable to different users or applications. This suits WordPress, where a single site could power several applications (such as website and mobile app) and be customized for different clients. The GraphQL API makes this behavior explicit through the “custom endpoints” feature, which enables to create different endpoints, with access to different GraphQL schemas, for different users or applications.

To avoid performance hits, the schema is made static by caching it to disk or memory, and it is re-generated whenever a new plugin extending the schema is installed, or when the admin updates the settings.

Support for novel features

Another benefit of using the code-first approach is that it enables us to provide brand-new features that can be opted into, before these are supported by the GraphQL spec.

For instance, nested mutations have been requested for the spec but not yet approved. The GraphQL API complies with the spec, using types QueryRoot and MutationRoot to deal with queries and mutations respectively, as exposed in the standard schema. However, by enabling the opt-in “nested mutations” feature, the schema is transformed, and both queries and mutations will instead be handled by a single Root type, providing support for nested mutations.

Let’s see this novel feature in action. In this query, we first query the post through Root.post, then execute mutation Post.addComment on it and obtain the created comment object, and finally execute mutation Comment.reply on it and query some of its data (uncomment the first mutation to log the user in, as to be allowed to add comments):

# mutation {
#   loginUser(
#     usernameOrEmail:"test",
#     password:"pass"
#   ) {
#     id
#     name
#   }
# }
mutation {
  post(id:1459) {
    id
    title
    addComment(comment:"That's really beautiful!") {
      id
      date
      content
      author {
        id
        name
      }
      reply(comment:"Yes, it is!") {
        id
        date
        content
      }
    }
  }
}

Dynamic behavior

WordPress uses hooks (filters and actions) to modify behavior. Hooks are simple pieces of code that can override a value, or enable to execute a custom action, whenever triggered.

Is there an equivalent in GraphQL?

Directives to override functionality

Searching for a similar mechanism for GraphQL, I‘ve come to the conclusion that directives could be considered the equivalent to WordPress hooks to some extent: like a filter hook, a directive is a function that modifies the value of a field, thus augmenting some other functionality.

For instance, let’s say we retrieve a list of post titles with this query:

query {
  posts {
    title
  }
}

…which produces this response:

{
  "data": {
    "posts": [
      {
        "title": "Scheduled by Leo"
      },
      {
        "title": "COPE with WordPress: Post demo containing plenty of blocks"
      },
      {
        "title": "A lovely tango, not with leo"
      },
      {
      "title": "Hello world!"
      },
    ]
  }
}

These results are in English. How can we translate them to Spanish? With a directive @translate applied on field title (implemented through this directive resolver), which gets the value of the field as an input, calls the Google Translate API to translate it, and has its result override the original input, as in this query:

query {
  posts {
    title @translate(from:"en", to"es")
  }
}

…which produces this response:

{
  "data": {
    "posts": [
      {
        "title": "Programado por Leo"
      },
      {
        "title": "COPE con WordPress: publica una demostración que contiene muchos bloques"
      },
      {
        "title": "Un tango lindo, no con leo"
      },
      {
        "title": "¡Hola Mundo!"
      }
    ]
  }
}

Please notice how directives are unconcerned with who the input is. In this case, it was a Post.title field, but it could’ve been Post.excerpt, Comment.content, or any other field of type String. Then, resolving fields and overriding their value is cleanly decoupled, and directives are always reusable.

Directives to connect to third parties

As WordPress keeps steadily becoming the OS of the web (currently powering 39% of all sites, more than any other software), it also progressively increases its interactions with external services (think of Stripe for payments, Slack for notifications, AWS S3 for hosting assets, and others).

As we‘ve seen above, directives can be used to override the response of a field. But where does the new value come from? It could come from some local function, but it could perfectly well also originate from some external service (as for directive @translate we’ve seen earlier on, which retrieves the new value from the Google Translate API).

For this reason, GraphQL API has decided to make it easy for directives to communicate with external APIs, enabling those services to transform the data from the WordPress site when executing a query, such as for:

  • translation,
  • image compression,
  • sourcing through a CDN, and
  • sending emails, SMS and Slack notifications.

As a matter of fact, GraphQL API has decided to make directives as powerful as possible, by making them low-level components in the server’s architecture, even having the query resolution itself be based on a directive pipeline. This grants directives the power to perform authorizations, validations, and modification of the response, among others.

Localization

GraphQL servers using the SDL-first approach find it difficult to localize the information in the schema (the corresponding issue for the spec was created more than four years ago, and still has no resolution).

Using the code-first approach, though, the GraphQL API can localize the descriptions in a straightforward manner, through the __('some text', 'domain') PHP function, and the localized strings will be retrieved from a POT file corresponding to the region and language selected in the WordPress admin.

For instance, as we saw earlier on, this code localizes the field descriptions:

class UserFieldResolver extends AbstractDBDataFieldResolver
{
  public function getSchemaFieldDescription(
    TypeResolverInterface $typeResolver,
    string $fieldName
  ): ?string {
    $descriptions = [
      'username' => __("User's username handle", "graphql-api"),
      'email' => __("User's email", "graphql-api"),
      'url' => __("URL of the user's profile in the website", "graphql-api"),
    ];
    return $descriptions[$fieldName];
  }
}

User interfaces

The GraphQL ecosystem is filled with open source tools to interact with the service, including many provide the same user-friendly experience expected in WordPress.

Visualizing the GraphQL schema is done with GraphQL Voyager:

GraphQL Voyager enables us to interact with the schema, as to get a good grasp of how all entities in the application’s data model relate to each other.

This can prove particularly useful when creating our own CPTs, and checking out how and from where they can be accessed, and what data is exposed for them:

Interacting with the schema

Executing the query against the GraphQL endpoint is done with GraphiQL:

GraphiQL for the admin

However, this tool is not simple enough for everyone, since the user must have knowledge of the GraphQL query syntax. So, in addition, the GraphiQL Explorer is installed on top of it, as to compose the GraphQL query by clicking on fields:

GraphiQL with Explorer for the admin

Access control

WordPress provides different user roles (admin, editor, author, contributor and subscriber) to manage user permissions, and users can be logged-in the wp-admin (eg: the staff), logged-in the public-facing site (eg: clients), or not logged-in or have an account (any visitor). The GraphQL API must account for these, allowing to grant granular access to different users.

Granting access to the tools

The GraphQL API allows to configure who has access to the GraphiQL and Voyager clients to visualize the schema and execute queries against it:

  • Only the admin?
  • The staff?
  • The clients?
  • Openly accessible to everyone?

For security reasons, the plugin, by default, only provides access to the admin, and does not openly expose the service on the Internet.

In the images from the previous section, the GraphiQL and Voyager clients are available in the wp-admin, available to the admin user only. The admin user can grant access to users with other roles (editor, author, contributor) through the settings:

The admin user can grant access to users with other roles (editor, author, contributor) through the settings.

As to grant access to our clients, or anyone on the open Internet, we don’t want to give them access to the WordPress admin. Then, the settings enable to expose the tools under a new, public-facing URL (such as mywebsite.com/graphiql and mywebsite.com/graphql-interactive). Exposing these public URLs is an opt-in choice, explicitly set by the admin.

Granting access to the GraphQL schema

The WP REST API does not make it easy to customize who has access to some endpoint or field within an endpoint, since no user interface is provided and it must be accomplished through code.

The GraphQL API, instead, makes use of the metadata already available in the GraphQL schema to enable configuration of the service through a user interface (powered by the WordPress editor). As a result, non-technical users can also manage their APIs without touching a line of code.

Managing access control to the different fields (and directives) from the schema is accomplished by clicking on them and selecting, from a dropdown, which users (like those logged in or with specific capabilities) can access them.

Preventing conflicts

Namespacing helps avoid conflicts whenever two plugins use the same name for their types. For instance, if both WooCommerce and Easy Digital Downloads implement a type named Product, it would become ambiguous to execute a query to fetch products. Then, namespacing would transform the type names to WooCommerceProduct and EDDProduct, resolving the conflict.

The likelihood of such conflict arising, though, is not very high. So the best strategy is to have it disabled by default (as to keep the schema as simple as possible), and enable it only if needed.

If enabled, the GraphQL server automatically namespaces types using the corresponding PHP package name (for which all packages follow the PHP Standard Recommendation PSR-4). For instance, for this regular GraphQL schema:

Regular GraphQL schema

…with namespacing enabled, Post becomes PoPSchema_Posts_Post, Comment becomes PoPSchema_Comments_Comment, and so on.

Namespaced GraphQL schema

That’s all, folks

Both WordPress and GraphQL are captivating topics on their own, so I find the integration of WordPress and GraphQL greatly endearing. Having been at it for a few years now, I can say that designing the optimal way to have an old CMS manage content, and a new interface access it, is a challenge worth pursuing.

I could continue describing how the WordPress philosophy can influence the implementation of a GraphQL service running on WordPress, talking about it even for several hours, using plenty of material that I have not included in this write-up. But I need to stop… So I’ll stop now.

I hope this article has managed to provide a good overview of the whys and hows for satisfying the WordPress philosophy in GraphQL, as done by plugin GraphQL API for WordPress.


The post Rendering the WordPress philosophy in GraphQL appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

My Long Journey to a Decoupled WordPress Gatsby Site

As a professional research biologist, my playground used to be science laboratories filled with microscopes, petri dishes, and biology tools. Curiosity leads many scientists on their journey to discoveries. Mine led me to web design. I used to try learning HTML on my lab desktop while centrifuging extraction samples or waiting for my samples to thaw or freeze. These wait times are valuable for writing experiment notes and even learn a new skill. For me, this meant learning basic HTML through editors, like HomeSite and later Dreamweaver, as well as many other online resources.

After leaving my science lab desk about a decade ago, I found a new playground. I was introduced to WordPress by a local web developer friend. This changed the course of my life. Learning web design is no longer a downtime activity — it has become the main activity of my daily life.

My first step: Learning theme development

I call myself a WordPress enthusiast and an avid WordPress user. I entered into the world of WordPress by learning to hack themes, my virtual guru“Building Themes from Scratch Using Underscores” by Morten Rand-Hendriksen. While learning to develop themes, I must have watched this tutorial countless times and quickly it became my go-to reference. While doing my learning projects, I often referred to Morten’s GitHub repository to learn from his themes. For my personal sites, I used my own themes which are inspired by Morten’s, like Kuhn, Popper and others.

I also learned how to build plugins and widgets for my own site, but I mostly stayed within theming. I built themes for my personal sites. My personal sites are like my three-ring binders: one for every subject area. My sites discourage search engines and are designed for archiving my personal learning and posting notes. This habit of writing and documenting every aspect of my projects was inspired by “Just Write” by Sara Soueidan.

A call to Learn JavaScript deeply

It all started with Matt Mullenweg‘s  call for WordPress developers to “learn JavaScript deeply” during the 2015 State of the Word address and the subsequent announcement of the Gutenberg block editor. Until then, I was a happy WordPress user and an aspiring WordPress developer. It was reported that JavaScript and API-driven Interfaces are the future of WordPress. Like other WordPress enthusiasts, I also acknowledged that JavaScript was  a must-have skill for WordPress development.

Thus, began my own JavaScript learning journey and road map. I used Zell Liew’s article “Learning JavaScript — where should you start and what to do when you’re stuck?”

Let me share my learning journey with you.

I started by looking at React and REST API-based themes

Since the official integration of the REST API in WordPress core, a few React-based themes have started popping up.

In my opinion, these themes appeared to be experimental. When the Foxhound theme was released, it was covered in CSS-Tricks as well as WordPress Tavern. I downloaded it to my test site, and it worked fine; however, I could not hack and learn from it given my limited familiarity with JavaScript and React.

I started digging into React

I used Robin Wieruch’s article “JavaScript fundamentals before learning React” as my JavaScript/React learning road map. While struggling to learn and understand React routing, I discovered Gatsby which utilizes @reach/router as a built-in feature, making routing a breeze. In my brief exploratory research, I learned that Gatsby is indeed a “React-based framework that helps developers build blazing fast websites and apps.” This led me to learn Gatsby while continuing to make progress on React. After a while, I immersed myself in my Gatsby projects and only occasionally returned to learning basic JavaScript and React.

I picked up Gatsby

Given that I had already done several small learning projects in React, understanding Gatsby was natural. Gatsby is said to be aimed at developers and not users. I did not find it that hard to learn and run my own simple Gatsby test sites.

Gatsby’s documentation and tutorials are well-written, helpful, and easy to follow. I decided to learn Gatsby using its tutorials and completing all eight parts as a means of “learning by doing.” While working on my projects, I consulted other guides and tutorial posts. The following two guides helped me to understand build concepts, add functionality and put together a reasonable Gatsby demo site:

For styling React components, there are several options which are covered on CSS-Trick. Some options include local inline CSS-in-JS, styled components and modular CSS. Gatsby components can also be styled with Sass using gatsby-plugin-sass, which makes the code more readable. Because of its familiarity and code readability, I chose styling with Sass; however, I recognize the value of CSS modules as well.

Resources for integrating Gatsby and WordPress

My Gatsby learning didn’t stop there. In fact, Gatsby has been the most significant part of my learning curve more recently. Here’s everything I found throughout my learning journey that I hope will serve you as well on your own journey.

There are many sites already running on Gatsby. Those who have migrated to Gatsby seem to be happy, especially with the blazingly fast speed and the improved security it offers.

Commenting in Gatsby

WordPress has natively supported comments for a long, long time. Gatsby sites are serverless-static, so posting comments is an issue since they are dynamic and requires a client side service.

Some Gatsby and React developers seem to leave commenting and interactions on their own personal sites to Twitter. Others seem to reach for Disqus. If you are interested, this Northstack tutorial describes in detail how to bring WordPress comments over to Gatsby.

WordPress Gatsby themes

I first became aware of WordPress ported Tabor for Gatsby theme from WordPress Tavern. It was developed by Rich Tabor and is freely available on GitHub (demo). From there, two WordPress-inspired Gatsby themes became available through the Gatsby Theme Jam project. One was by Alexandra Spalato called Gatsby Theme WordPress Starter (demo) and the other by Andrey Shalashov called WordPress Source Theme (demo).

In 2019, a team of Gatsby and WPGraphQL developers led by Jason Bahl, Muhammad Muhsin, Alexandra Spalato, and Zac Gordon announced a project that ports WordPress themes to Gatsby. Zac, talking to WordPress Tavern, said the project would offer both free and paid premium themes. At the time of this writing, five themes were listed with no free download.

Decoupled Gatsby WordPress starters

The current Gatsby starer library lists ten WordPress-compatible starter themes, including a more recent one by Henrik Wirth that ports the WordPress Twenty Twenty theme — stylesheets and fonts — to Gatsby. Although the theme is still a work-in-progress with some limitations (e.g. no support for tags, monthly archives, and comments). Nevertheless, it is a great project and uses a new experimental Gatsby Source plugin for WordPress.

Another popular starter is gatsby-starter-wordpress by Gatsby Central.

Gatsby WordPress themes from GitHub

There are other popular Gatsby themes that are available at GitHub. The Twenty Nineteen WordPress Gatsby Theme is a port of the Twenty Nineteen WordPress Theme by Zac Gordon and Muhammad Muhsin.

Experimental plugins

There are also two new GraphQL plugins for WordPress that are under development and only available on GitHub at the moment. One is Gatsby Source WordPress Experimental by Tyler Barnes. This is a re-written version of current Gatsby Source WordPress plugin using WPGraphQL for data sourcing, as well as a custom WPGatsby plugin that transforms WPGraphQL schema in Gatsby-specific ways.

The other one is Gatsby WordPress Gutenberg which is still being developed by Peter Pristas. Its documentation is available over at the GatsbyWPGutenberg Docs site.

Step-by-step guides

Despite the ongoing progress in Gatsby WordPress theme development, I could not locate any detailed how-to guides written for beginners like me. Mohammad Mohsin wrote up a thorough guide over at Smashing magazine in 2018, explaining how he developed his Celestial React theme using the WordPress REST API. The other tutorial is another one he wrote about porting the Twenty Nineteen WordPress Theme to Gatsby, which uses WPGraphQL for WordPress data sourcing.

More recently, there have been two additional guides that I’ve benefited from:

Finally, my own partially ported Gatsby site

Everything covered so far is what has fueled me to create my own WordPress Gatsby site. While it was a large technical task, the guides I’ve referenced, in addition to the experimental plugins and existing documentation for Gatsby made it so much easier than if I had attempted to figure it out on my own.

Here is the result. While it’s still a work in progress, it’s awesome to see it working. I’ve written up a complete step-by-step walkthrough on how I made it, which will publish next week here on CSS-Tricks. So stay tuned!

What’s next on the horizon for Gatsby and WordPress?

I am still keeping my eyes on the two experimental WordPress plugins I mentioned earlier. I plan to revisit the project once those are officially released, hopefully in the WordPress Plugin Directory. This recent tweet thread highlights the current status of porting content from the WordPress block editor to a decoupled WordPress Gatsby theme.

In a recent WordCamp Spain 2020 session, Matt Mullenweg said that the demand for decoupled WordPress sites is growing:

But for people who are building more advanced applications or have some sort of constraint on their website where they need the React frontend, I think the decoupled use case of WordPress is stronger than ever. 

Dan Abramov agrees:

Taking with Sarah Gooding of WPTavern, Gatsby WP Themes project members Zac Gordon and Jason Bahl also confessed that the “most current Gatsby WordPress themes are directed for businesses and developers, they are not suitable for beginners.” Let’s hope the future fixes that!

My personal take

Based on my very limited experience, I think that currently available Gatsby WordPress themes are not ready for prime time use for users like me. Yeah, it is exciting to try something on the bleeding edge that’s clearly in the minds of many WordPress users and developers. At the same time, the constantly evolving work being done on the WordPress block editor, WPGraphQL and Gatsby source WordPress plugins makes it difficult to predict where things are going and when it will settle into a state where it is safe to use in other contexts. Until then, it’s a frustrating experience to work on something only to have the API or the interface change on you.

For my own personal uses, a normal Gatsby site is enough, I could get content with Markdown files without any hassles associated with decoupling WordPress. For larger agency sites… I can see why having a decoupled solution would make a lot of sense for them and their clients.

Remember, I’ll be sharing my tutorial next week — see you then!


The post My Long Journey to a Decoupled WordPress Gatsby Site appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Getting Started With the Puppeteer API for Headless Chrome

Google Chrome is, by far, the most mainstream web browser with its best of all security features and enhanced functionality. It’s easy to use and smooth surfing capabilities have made it the most sought after browser. The concept of web browser automation has been in practice for some time now. Automating browsers, to scrap carrying out redundant and repetitive tasks like screen navigation, filling out forms, taking screenshots, etc that hamper the speed of any application, is a methodology every developer follows. There are various multi-browser automation tools like Selenium, being one of the most popular, as well as other dedicated browser extensions like Chrome Browser extension (CBA) for Chrome, that help carry out smooth web browser automation.

The Rise of Headless Chrome and Puppeteer

In reference to this context, Google Chrome introduced the Headless Chrome functionality to allow automating the browser in a headless mode. The Headless Chrome enables the complete execution of Google Chrome on servers that run without a Graphical User Interface (GUI). It lets you programmatically test your web app without the need for any frontend framework. The entire automated testing process is carried out in the background, without you seeing anything happening in the testing process. Headless Chrome has gained immense popularity in the field of web development, due to its swift and fast execution.

“Headless Mode”

A couple of months ago, we invited Marc Anton Dahmen to show off his database-less content management system (CMS) Automad. His post is an interesting inside look at templating engines, including how they work, how CMSs use them, and how they impact the way we write things, such as loops.

Well, Automad just released version 1.3.0 and it introduces a "headless" mode that brings it more in line with where the CMS landscape seems to be headed (pun intended).

And what the heck is a "headless" CMS? I always find that name to be a little weird, but the idea is that the engine for content creation is fully separated from the front-end display and instead stitched together by APIs. This means we're able to get all the wonderful benefits of creating content in a CMS without being locked into its templating requirements. Chris has a more thorough explanation of the concept from a few years back.

A good example is WordPress and its REST API. We still enjoy the easy UI and extensible administrative features of WordPress, but can send the data anywhere via API to create the front end. Rather write your templates in JavaScript instead of PHP? Go for it!

If the CMS is a body and the front-end view is the head, then the body can unscrew its head and replace it with another. Weird, right?

In any case, whether it's Automad, WordPress, Sanity, Contentful, Ghost, Netlify CMS, or any others in the growing number of API-first options out there, the move toward headless is a space to watch. HeadlessCMS.org is a good place to do that. We could see vast changes that lead to both better content and developer experiences, which is what all of this is trying to accomplish.

The post “Headless Mode” appeared first on CSS-Tricks.

JAMstack CMSs Have Finally Grown Up!

This article is based on Brian's presentation at Connect.Tech 2019. Slides with speaker notes from that presentation are available to download.

In my experience, developers generally find the benefits of the JAMstack easy to comprehend. Sites are faster because the resources are static and served from a CDN. Sites are more secure because there is no framework, application server or database to compromise. Development and deployment can be optimized because all of the pieces that make up the stack are unbundled. And so on.

What can be more difficult for developers to comprehend are the trade-offs that this can often require for the folks who create and edit content. Traditional, monolithic content management systems have often been ridiculed by developers (yes, even WordPress) who became frustrated trying to bend the tool to their will in order to meet project requirements. But, until recently, the JAMstack largely just passed that burden onto the non-technical content creators and editors.

By developers, for developers

Static site generators (i.e. tools like Jekyll, Hugo and Gatsby) grew enormously in popularity in large part because developers adopted them for projects. They became common solutions for things like blogs, documentation or simple static pages. By and large, these were sites created by developers, maintained by developers and with the content primarily written and edited by developers.

When I first wrote about these tools in a report for O'Reilly in 2015, this is what I said:

Just in case this isn’t already clear, I want to emphasize that static site generators are built for developers. This starts with the development of the site all the way through to adding content. It’s unlikely that non-developers will feel comfortable writing in Markdown with YAML or JSON front matter, which is the metadata contained at the beginning of most static site engine content or files. Nor would non- technical users likely feel comfortable editing YAML or JSON data files.

—Me (Static Site Generators report for O'Reilly 2015)

When, two years later, I wrote a book for O'Reilly on the topic (with my friend Raymond Camden), not too much had changed. There were some tools at the very early stages, including Jekyll Admin and Netlify CMS, but they had not matured to a point that they could realistically compete with the sort of WYSIWYG tooling that content editors were used to in tools like WordPress.

The WordPress editor showing a field for the post title and a text area for the post content.
The WordPress editing experience

By contrast, the editing experience of static CMSs still required an understanding of Markdown and other markup (YAML, Liquid, etc.).

An editing screen in Netlify showing post fields on the left and a preview of the post on the right.
The Netlify CMS editing experience in 2017

Suffice it to say, whatever the technical merits of the architecture at the time, from a content editing standpoint, this was not a toolset that was ready for mainstream adoption.

The awkward teenage years

Over the ensuing two years, a combination of a couple of trends started to make the JAMstack a viable solution for mainstream content sites with non-technical editors. The first was that the static CMS matured into what we now generally refer to as git-based CMS solutions. The second was the rise of the headless, API-first CMS as a solution adopted by enterprises.

Let's take a look at the first trend... well... first. Netlify CMS, an open-source project from Netlify, is an example of a git-based CMS. A git-based CMS doesn't store your content, as a traditional CMS would, but it has tools that understand how to edit things like Markdown, YAML, JSON and other formats that make up a JAMstack site. This gives the content editors tools they feel comfortable with, but, behind the scenes, their content changes are simply committed back into the repository, forcing a rebuild of the site. While Netlify CMS is installed on the site itself, other popular git-based CMS options are web-based, including Forestry and DatoCMS.

An editing screen in Netlify from 2017 showing post fields on the left and a preview of the post on the right.
The current editing experience in Netlify CMS

The headless, API-first CMS functions much more like the editing experience in a traditional CMS. It not only offers tools for creating and editing content, but it stores that content. However, it makes that content available to the front end - any front-end - via an API. While not limited to JAMstack in any way, an API-first CMS works well with it because the creation and management of the content is separate from the display of that content on the front end. In addition, many API-first CMSs offer pre-built integrations with some of the most widely used static site generators. Popular API-first options include Contentful and Sanity.

The Contentful admin, showing post fields on the left and post settings on the right.
Contentful

HeadlessCMS.org is a site maintained by Netlify that has a comprehensive list of all the available tools, both git-based and API-first. For a good look at the differences, pros and cons between choosing a git-based versus an API-first CMS, check out this post by Bejamas.

Both git-based and API-first headless CMS options began to give non-technical content editors the tools they needed on the backend to create content. The awkwardness of these "teenage years" comes from the fact that the tooling is still disconnected from the frontend. This makes it difficult to see how changes you've made in the backend will impact the frontend until those changes are actually committed to the repo or pushed live via the API. Add in the time cost of a rebuild and you have a less than ideal editing experience where mistakes can more easily make it to the live site.

A Look at the future

So what does the future look like when the JAMstack CMS is finally grown up? Well, we got a good look at this year's JAMstack_conf_sf. Coincidentally, there were two presentations demonstrating new tools that are bringing the content editing experience to the frontend, letting content editors see what they are changing, how their changes will look and how they will impact the layout of the site.

The first presentation was by Scott Gallant of Forestry. In it, he introduced an new open source projects from Forestry called TinaCMS that brings a WYSIWYG style content editing experience to the frontend of sites that use a git-based CMS and Gatsby or Next.js (both React-based tools).

Animated flow for editing a page on the front end with Tina CMS.
TinaCMS

The second presentation was by Ohad Eder-Pressman of Stackbit (full disclosure: I work as a Developer Advocate for Stackbit) that introduced an upcoming set of tools called Stackbit Live. Stackbit Live is designed to be CMS and static site generator agnostic, while still allowing on-page editing and previewing of a JAMstack site.

Animation of editing a page on the front end with Stackbit Love
Stackbit Live

What both these tools demonstrated is that we're at a point where a "JAMStack + headless" architecture is a real alternative to a traditional CMS. I believe we've reached the tipping point whereby we're no longer trading a great developer experience for an uncomfortable editing experience for content authors. By 2020, JAMstack CMS will officially be all grown up. 👩🏽‍🎓

The post JAMstack CMSs Have Finally Grown Up! appeared first on CSS-Tricks.

JAMstack Tools and The Spectrum of Classification

With the wonderful world of JAMstack getting big, all the categories of services and tools that help it along are as important as ever. There are static site generators, headless CMSs, and static file hosts.

I think those classifications are handy, and help conversations along. But there is a point where nuance is necessary and these classification buckets get a little leaky.

Note, these charts are just intended to paint a spectrum, not to be a comprehensive list of services.

Headless CMSs

A Headless CMS is a CMS that provides an admin area for creating and editing content, but offers no front-end to build the website from. All the content is accessed via APIs.

Imagine WordPress, which has an admin area, but it also has themes from which you build the website from on the server-side, with all kinds of PHP functions for you to use the content data. All that theming stuff is the "head". So a headless CMS would be like WordPress with just the admin area. And indeed you can use it that way, as it offers APIs.

There is even more nuance here, as there are services that offer an admin area, but don't actually store the data for you. Plus there is CMSs that are hosted for you, and CMSs where you have to bring your own hosting. Let's have a peak.

Service Headless? Hosting Notes
Contentful Yes Cloud A classic headless CMS
Sanity JSON data structure, accessed via APIs, custom admin area is self-hosted
Cockpit Self Comes with admin UI
Strapi
KeystoneJS All code, not even an admin UI
WordPress Sorta – Usually used with head Self or Cloud Has a head, but you don't have to use it, you choose to only use APIs to access content if you wish.
Drupal Self
CraftCMS Self Specifically has a headless mode and GraphQL API. Craft Cloud will bring a cloud-hosted headless varient
NetlifyCMS Sorta - Doesn't actually store content, just helps edit it. GUI for Git-hosted Markdown
Forestry Cloud
Joomla No Self A classic headed CMS
Squarespace Cloud Site builder, meant to build hosted/headed sites
Wix

Static Site Hosts

This is tricky to talk about because literally, any web host will host static files, and probably do an OK job of it. I think it's most useful to consider hosts that only do static hosting on purpose because it means they can optimize for that situation do other useful things.

Service Notes
Netlify The gold standard in static file hosts right now. Developer conviences galore.
Cloudflare Workers Sites CDN-first static file hosting alongside a cloud functions service.
Firebase Hosting Firebase is a whole suite of sub-products, but the hosting in particular is static and on a CDN.
GitHub Pages Static file host, but will also run Jekyll and other actions. Is not a CDN.
Neocities Static file host with online editor and community.
S3 Raw file storage. Can be configured to be a web host. Not a CDN unless you put CloudFront in front of it.
Bluehost Not really a static file host.
MediaTemple
Hostgator

Sometimes you'll see people trying to use stuff like Dropbox or Google Drive to do static file hosting (for a website), but I've found these services generally ultimately don't like that and prevent the use for that. If it works today, fine, but I wouldn't count on any of them long term.

Static Site Generators

You would think this category would be straightforward, without much spectrum. A static site generator takes input and makes statically generated pages that can render without, say, needing to hit a database. But even here there is a spectrum.

The language the generator is in kinda matters. It affects speed. It affects installability on different local platforms. It affects your ability to write code to extend it and hack on it.

But perhaps more importantly, not all static site generators are only static site generators. Some can be run on the server as well, weirdly enough. And there are some that kinda look like static site generators, but are more correctly classified as flat-file CMSs.

Software Lang Notes
Jekyll Ruby One of the originals in this generation of static site generator.
Hugo Go Known for speed.
11ty Node Processes 11 different template languages out of the box.
Gatsby React Gatsby is truly a static site generator, but generally, the sites "hydrate" into SPAs, but remain static (nothing server-rendered). Big ecosystem of plugins to help with connecting data sources, handling images, etc.
Next Next can do static site generation, but it can also run live in Node and do server-side rendering on the fly ("Isomorphic JavaScript").
Nuxt Vue Nuxt is the spirtiual companion to Next but in Vue. It also can either be staticly generator or run isomorphicly.
Kirby PHP Kirby runs from static files (no database), but isn't really a static site as the pages are rendered by PHP.
Statamic Statamic is similar to Kirby in that static files are used for data but the page themselves are rendered by PHP.
Perch Just an example of a CMS that keeps data in a database and isn't trying to be a static site generator at all.

The post JAMstack Tools and The Spectrum of Classification appeared first on CSS-Tricks.

Learn How to Rapidly Create a Customized CMS a Java Framework!

Over the years of being a freelance developer for small to medium businesses, there has been one constant, CRUD applications. They usually consisted of some sort of ‘backend’ that handled the content of an app or website.

Well, for a website, the solution is easy; Wordpress, or maybe Joomla?

Building a Website With Gatsby and a Headless CMS

If you’re looking to launch a small, static, and speedy website, micro-site, or landing page, you may be considering a static-site generator like Gatsby.

This article will walk you through the process of using Gatsby alongside dotCMS, a Java-based open-source headless CMS, to build a static website that uses API calls to pull content that’s created, stored, and managed in dotCMS, and presented by Gatsby.