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:
The site is easy to maintain.
The tech is relatively simple.
There is great compatibility with WordPress plugins.
Cons:
Your site may feel a little dated as society expects app-like experiences in the browser.
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.
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:
The website itself will feel modern, and fast.
It’s easy to integrate with other RESTful services outside of WordPress.
The entire site is built in JavaScript, which makes it easier to build complex websites.
Cons:
You must re-invent a lot of things that WordPress plugins do out of the box for you.
This set up is difficult to maintain.
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:
This is easy to maintain, when set-up.
The hosting is as easy as a typical WordPress theme.
The website feels just as modern and fast as a headless website.
Cons:
You always have to think about two different methods to render your website.
There are limited choices for JavaScript libraries that are effective with this method.
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:
load a page using a WordPress request,
load a page using JavaScript,
allow pages to be identical, regardless of how they’re rendered,
provide a way to know when to load a page using JavaScript, or PHP, and
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:
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>
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:
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.
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 Dahaldigging 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.
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 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.
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.
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).
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:
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.
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.
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.
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.
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.
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!
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.
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.
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.
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!
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.
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.
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.
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.
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:
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.
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.
“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.
“Jason Bahl of WPGraphQL’s role in the operating system for the web” (YouTube): Here’s Jason again, this time discussing templating. He covers WPGraphQL’s role in the WordPress ecosystem and headless Gatsby sites, emphasizing that WPGraphQL is all about data exposure, just like the WordPress REST API. How the WPGraphQL exposes WordPress data in Gatsby and displays it in front-end React components is up to developers.
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.
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!
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.
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.
😕
🤓
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.
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.
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
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.)
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.
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!
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.
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:
Category
WordPress app expected behavior
Interpretation for GraphQL service running on WordPress
Accessing data
Democratizing publishing: Any user (irrespective of having technical skills or not) must be able to use the software
Democratizing 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
Extensibility
The application must be extensible through plugins
The GraphQL schema must be extensible through plugins
Dynamic behavior
The behavior of the application can be modified through hooks
The results from resolving a query can be modified through directives
Localization
The application must be localized, to be used by people from any region, speaking any language
The GraphQL schema must be localized, to be used by people from any region, speaking any language
User interfaces
Installing and operating functionality must be done through a user interface, resorting to code as little as possible
Adding 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 control
Access to functionalities can be granted through user roles and permissions
Access to the GraphQL schema can be granted through user roles and permissions
Preventing conflicts
Developers 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 possible
Developers 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:
getSchemaFieldArgs: to declare the field arguments (including their name, description, type, and if they are mandatory or not)
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:
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.
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.
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:
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:
Executing the query against the GraphQL endpoint is done with GraphiQL:
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:
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:
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:
…with namespacing enabled, Post becomes PoPSchema_Posts_Post, Comment becomes PoPSchema_Comments_Comment, and so on.
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.
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.
Picard: This theme was developed by Automattic as an experimental prototype WordPress theme that makes use of React and the new WP-API. Its GitHub repository has not been updated in five years and its usage is not known.
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.
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.
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.
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:
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.
Has anyone successfully used the block editor with a decoupled #WordPress setup? I haven’t tried but have heard some rumblings it doesn’t work, or doesn’t work well. Curious to hear from folks.
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:
This hits the nail on the head. And is 100% matching our long term thinking. Client-side-only is not sustainable. We need to move more stuff to the server, but without sacrificing seamless composition of interactive pieces. https://t.co/O4LX8JacRo
Taking with Sarah Gooding of WPTavern, GatsbyWP 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!
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.
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.
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.
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 editing experience
By contrast, the editing experience of static CMSs still required an understanding of Markdown and other markup (YAML, Liquid, etc.).
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.
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.
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).
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.
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. 👩🏽🎓
This Refcard overviews the Headless CMS, explains its advantages over Traditional and Hybrid systems, and a provides a step-by-step tutorial for putting Headless CMS into practice.
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.
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.
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.
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.
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?
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.