Use WordPress as a headless CMS
What is a headless CMS? How can it help you build more robust, scalable website? Let's find out.
I first heard about the headless CMS approach in a talk I watched from Twin Cities Drupal. I liked the idea of a separation of concerns between authoring content and viewing it.
I had already experienced how easily one server can go down, taking out all of the sites on it, leading to minutes or hours of heart-stopping panic (there were 24 on mine). I had also seen how a monolithic CMS-based site could suffer a security compromise and take a lot of effort to repair (that took me more than two days of unpaid work). For a range of web hosting provider options, check out our guide.
I'd seen the benefits of CDNs (content delivery networks) that can store your image, audio and video files on servers optimised for fast delivery and can duplicate those files across the world for speedy delivery to those regions if needed. What if your entire website could benefit from this approach?
● A computer with an internet connection (obvs)
● A code editor (Atom or VS Code)
● A command line shell / terminal
● A recent version of Node.js installed (you can download & install here)
● A WordPress site to get content from. If you don't have one, you can use the WordPress.com platform or this Heroku build pack.
● The source files from GitHub.
Getting started
WordPress comes out of the box with the REST API and that is what we're going to use to query your data. So we don't really need anything else! Our display site is totally separate from our content site, so we won't need WordPress themes or any other customisation outside a few (optional) plugins. Although of course you can add these if you want to.
The exception is if you need custom meta fields for extra content areas. You're probably using Advanced Custom Fields to do so; you can add that data to the WordPress API by installing this plugin.
Use a static site generator
Now that we have our content source, let's fetch the data and display it using a static site generator. My weapon of choice in this realm is Gatsby, an excellent static site generator that's built with JavaScript. (See these website builder picks for simple ways to build a site.)
If you're looking for a good way to build on your JavaScript skills and learn React by getting stuck into some code, I highly recommend trying Gatsby to do so. I've learned a lot myself by playing with it.
Get the Creative Bloq Newsletter
Daily design news, reviews, how-tos and more, as picked by the editors.
First, let's install a command-line tool that allows us to create Gatsby sites:
npm install -global gatsby-cli
Now, navigate to the folder where you want to keep your site and run this command:
gatsby new blog
This will create a new folder called 'blog' and install Gatsby and its dependencies to this folder. Open this folder in your favourite text editor. There might seem to be a lot of files there. Don't worry, we'll only be directly editing the gatsby-config.js, gatsby-node.js files, and the src folder, which is where our templates live.
If you've got a lot of files to store, it's worth upgrading your cloud storage.
Getting our content
The first step we want to take is to fetch our content from the WordPress site's API.
To do that, we're going to install gatsby-source-wordpress, a prewritten plugin for WordPress. This illustrates one of the main reasons I love Gatsby – you can get your data from a variety of different sources. A lot of static site generators are restricted to using Markdown files but Gatsby is very flexible.
Gatsby's plugin ecosystem is very mature. There are loads of prewritten ways of getting your data and lots of other clever functionality that comes in useful too.
To install the plugin, first change directory into your new Gatsby site by using this command: cd blog.
Now run this command: npm install --save gatsbysource-wordpress.
Once that's done, it's time to open up the gatsby-config.js file. You'll see that there is already some basic setup in place that Gatsby gives us by default. We're going to build on that to configure our plugin here:
module.exports = {
siteMetadata: {
title: 'Gatsby Default Starter',
},
plugins: [
'gatsby-plugin-react-helmet',
{
resolve: "gatsby-source-wordpress",
options: {
baseUrl: "my-wordpress-site.com",
protocol: "https",
hostingWPCOM: false,
useACF: true,
searchAndReplaceContentUrls: {
sourceUrl: "https://my-wordpress-site.com",
replacementUrl: "https://my-static-site.com",
}
},
},
],
}
Did it work?
You can check by opening your terminal, typing gatsby develop and watch what happens. Be warned! Even if you got your settings correct, you will get some warnings anyway – this may be Gatsby looking for content that you haven't written yet.
You are now able to view gatsby-starter-default in the browser.
http://localhost:8000/
View GraphiQL, an in-browser IDE, to explore your site's data and schema.
http://localhost:8000/___graphql
Note that the development build is not optimised. To create a production build, use gatsby build.
If the Gatsby default starer (right) isn't what you're getting, check your WordPress site isn't on a subdomain, that it's definitely using HTTPS or HTTP and that you have the same in your settings.
Now we can go to http://localhost:8000/ and see our Gatsby site!
Can we query our data?
You may have noticed that there is no WordPress content here. This is because we haven't told Gatsby what to do with it yet. Before we do that, let's just check we have actually got our content available to Gatsby. To do that, visit this url:
http://localhost:8000/___graphql
This built-in tool is called GraphiQL and is another secret power of Gatsby.
GraphQL is similar to REST: it's a way to query data. But with GraphQL, you can interact with your data much more easily. GraphiQL (a visual IDE for GraphQL) can show us some of these tricks. On the left panel, try typing the following:
{
allWordpressPost {
edges {
node {
id
slug
status
template
format
}
}
}
}
This might look a bit like JSON but it's not. It's a new query language that I think one day will largely replace REST as a way of communicating with APIs.
What did you get when you pressed ctrl + enter in GraphiQL? You hopefully will have seen your WordPress posts and page on the right-hand side of the screen.
We are actually going to use this query in our next step, so keep it handy! You might want to see what other data you can get with GraphiQL while you're here. If you want to do that, try moving the cursor around and typing either ctrl + space and / or ctrl + enter. That will reveal other groups of content.
So, we now have content in Gatsby. Next, we need to display it.
Display our posts
For this next step we're going to be making use of the gatsby-node.js file.
gatsby-node.js is a file you can use to interact with Gatsby's "Node API". Here you can control how your site is generated and create pages, posts and more.
We're going to write some instructions here to tell Gatsby what to do with our data:
const path = require(`path`);
exports.createPages = ({ graphql, boundActionCreators })
=> {
const { createPage } = boundActionCreators
return new Promise((resolve, reject) => {
graphql(
`
{
allWordpressPost {
edges {
node {
id
slug
status
template
format
}
}
}
}
`
).then(result => {
if (result.errors) {
console.log(result.errors)
reject(result.errors)
}
const postTemplate = path.resolve(`./src/templates/
post.js`)
result.data.allWordpressPost.edges.forEach(edge => {
createPage({
path: `/${edge.node.slug}/`,
component: postTemplate,
context: {
id: edge.node.id,
},
})
})
resolve()
})
})
}
This code creates pages from our GraphQL query and for each page it'll use a template we've defined (/src/templates/post.js). So next, we need to create that file!
Create post template
Inside the /src/ folder, create a folder called templates and a file inside that's called post.js. Add to it this code:
import React from 'react'
import Helmet from 'react-helmet'
class postTemplate extends React.Component {
render() {
const post = this.props.data.wordpressPost;
const slug = this.props.data.wordpressPost.slug;
return (
<div>
<Helmet title={`${titleString} | ${siteTitle}`} />
<h1 dangerouslySetInnerHTML={{ __html: post.title }} />
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</div>
)
}
}
export default pageTemplate
export const query = graphql`
query currentPost($id: String!) {
wordpressPost(id: { eq: $id }) {
title
content
slug
}
site {
siteMetadata {
title
}
}
}
This uses a different GraphQL query to get data about the specific post it's been fed by the gatsbynode.js file, then uses React to render that out into the browser.
If you want to quickly see a list of all your posts, you can type http://localhost:8000/a into your browser's address bar. This will take you to a development 404 page, which lists all of your posts. Click on one to visit it!
Next steps
We've scratched the surface of how to use WordPress as a headless CMS and I hope I've introduced you to some interesting concepts and tools that you might be able to use and experiment with in the future.
There's a lot more to this story and my colleagues and I have blogged about it extensively at Indigo Tree. I've also written more on my personal blog, Delicious Reverie.
Please keep in touch with me via those channels and on Twitter to hear more exciting developments in the world of headless CMS!
This article was originally published in issue 308 of net, the world's best-selling magazine for web designers and developers. Buy issue 308 here or subscribe here.
Related articles:
Thank you for reading 5 articles this month* Join now for unlimited access
Enjoy your first month for just £1 / $1 / €1
*Read 5 free articles per month without a subscription
Join now for unlimited access
Try first month for just £1 / $1 / €1