Use WordPress as a headless CMS

Use WordPress as a headless CMS

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).

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?

You will need…

● 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

Use WordPress as a headless CMS: Gatsby starter screen

The Gatsby default starter screen

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.

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.

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.

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

Use WordPress as a headless CMS: Gatsby development 404 screen

Gatsby development 404 page showing all of our WordPress 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: