Raquel M Smith

Creating a Gatsby Front-End with a WordPress CMS

GatsbyJS is a relatively new website framework based on React that’s focused on creating incredibly fast websites. It does this by creating static pages at build time from whatever your preferred source, then serving up those static pages when requested. In addition, it has a number of other fancy techniques, including preloading other links on the page, only displaying critical parts of the page at load time, and more.

WordPress is an incredibly popular CMS that powers over 1/3 of the world’s top websites, and likely closer to 50% of websites overall. It makes a great CMS, but it has a few flaws: server-side rendering makes hosting expensive, even the best caching can’t beat the speed of static files, and it’s honestly not the most fun environment to develop in.

However, WordPress does truly make a great content management system, so pairing it with a Gatsby front-end is an interesting idea, and one that actually works quite well. In this post, I’ll go over my process for creating a Gatsby front-end using WordPress as a headless CMS.

Take the Gatsby Tutorial

To get started, I recommend taking the Gatsby Tutorial. It walks you through a lot of the Gatsby basics to get your oriented with the framework. It’s tempting to just jump right in with the starter template and see what you can do, but you’ll save a lot of time and frustration by going through the tutorial for an hour or two.

I should also mention that it’s important to have a basic understanding of developing with React in order to build a Gatsby site. It is based on React, after all, and all your building inside the framework will be done with React. I recommend taking Wes Bos’s course React for Beginners to get you up and running.

Start with the default Gatsby starter

The Gatsby website has a number of Starters – templates for Gatsby sites to get you up and running quickly. There are even a couple for WordPress that you can use to start pulling in the data you need.

When I evaluated these options, I felt like the WordPress starters made decisions for me that I didn’t necessarily prefer, and un-doing those decisions was a chore. Additionally, setting everything up from scratch allowed me to create exactly the site I wanted with no pre-determined decisions and really understand what was going on with my new Gatsby website.

The default Gatsby Starter is very bare-bones and only gives you the minimum files needed. Get it up and running with:

gatsby new my-new-site

Since you already took the tutorial, you should have an understanding of what happens here when you do that. So, I’m not going to go into it. If you’re confused… 👉https://www.gatsbyjs.org/tutorial/

Build out file structure

The Gatsby default /src folder comes with three directories – components, images, and pages.

  • Pages – Any file in pages becomes its own page (shocking!). These are one-off pages, like an About Me page, a contact page, a TOS page.
  • Components – These are bits and pieces you’ll use throughout your site, like the site header and footer. Any familiarity with React development should leave you with no question of what goes here.
  • Images – Any images you use across your website. If you’re pulling images in from an API, you won’t see them here, but when the site is built they will, indeed, live here.

We also want to add one more directory – templates. Templates are exactly what they sound like – a template used for dynamically creating pages based on data returned from your API. A single blog post, for instance, won’t get its own file in the pages directory because it’ll be created dynamically from the API data. Instead, Gatsby will use a template file to generate these pages when the site is built for production.

Template files are meant to be used multiple times. A blog archive doesn’t use a template file even though it uses API data because that file is only used once – to create a single blog archive.

You’ll likely need at least one template here for the single blog posts. If you’re creating other types of pages from API data you’ll also need template files for those. For instance, if you’re using WordPress to create pages, then creating those at build time with Gatsby, you’ll need a template file for pages. For my portfolio site, I have a template for my projects pages, which are written in WordPress and created at build time. So, a few examples might be:

  • singleBlog.js
  • singleProject.js
  • singlePage.js
  • singleProduct.js
  • singleDoc.js

No need to fill out these files yet, we’re just creating structure.

Add the WordPress query plugin to Gatsby

Gatsby has an official plugin for querying WordPress data: gatsby-plugin-wordpress. You’ll add this to your gatsby-config.js file. The documentation is quite good, especially for more advanced use-cases if you’re using WPML or ACF in your WordPress install.

However, for a more basic example, you can copy what i’ve used in my portfolio site: https://github.com/raquelmsmith/rms-portfolio/blob/master/gatsby-config.js#L34-L51

The only non-standard thing there is the **/projects route, which is a custom post type for my projects. If you have your own custom post types you can also add them there just like so.

Set up the page creation in gatsby-node.js

Now Gatsby is able to query the data, but it can’t do anything with it. To set this up, we need to tell Gatsby what pages to make using what data. We’ll do this in the gatsby-node.js file, and we’ll use our first graphQL query!

You can see an example of how I set up my gatsby-node.js file here: https://github.com/raquelmsmith/rms-portfolio/blob/master/gatsby-node.js

A couple things of note:

  1. There is only a single GraphQL query in the gatsby-node.js file. Any data you need to pull in gets added to that query. You can see mine has two sections – one for posts and one for projects. If you need to add more you add them just like I’ve done with these two.
  2. You don’t need to pull in all your post data here. You only need the things that are required for creating the pages. In this case, we need the id (which is the GraphQL-assigned ID) and the slug. Your page templates will use the id and its associated data to generate the content, and the slug is used for – you guessed it – the page slug when the page is created.
    • I also pull in the wordpress_id and pass that to the context for createPage() for the blog posts. This is because when I query for comments, I need to tell WordPress which post I’m looking for comments for. More on that later.
  3. For each type of data returned (again, I have posts and projects, two different types), you need to use the createPage() function on each type and each piece of data for each type (also called a node) independently. Your handy old map() function works well for this.
  4. The path is the URL where the pages will end up. For mine, I chose blog/${slug} for blog posts and projects/${slug}. Those URLs are where you’ll find the generated pages.
  5. Each node (eg. a single post, a single project) needs to be passed to a page template so that the page content can be generated. This is where your template files you made earlier are used.

Add Yoast SEO REST API plugin to WordPress

The last piece of set-up that we’ll want to do before actually building out our pages is add Yoast SEO data to the WordPress REST API responses. If you’re using another SEO plugin you can see if they automatically do this, or figure it out yourself. However, Yoast SEO is the most popular SEO plugin and it works for these purposes, so that’s what I’ve used.

Niels Garve published a Yoast to WordPress API plugin that adds any data saved in the post Yoast settings to the REST API response. Download the most recent release there and upload and activate on your WordPress install. Now we’ll be able to use these data in our Gatsby pages with React Helmet, which is already included in the Gatsby default starter.

Build out the single post template

Now that we’ve got all the basics set up, you can start building out your template files. At a minimum, you need to use a GraphQL query to get the info that you need, then use that info to populate the page content.

Here’s the query that I’m using: https://github.com/raquelmsmith/rms-portfolio/blob/9ad9cb5bf24f3959b9441e00a18525fd98360216/src/templates/single-blog.js#L59-L90

You’ll notice that this also includes a query for comments associated with the post. If you aren’t pulling in comments you can exclude that bit (as well as the $postId in the first line of the query).

When the query gathers the data, it’s passed to the component as this.props.data. You can assign that as I’ve done to a variable to make it easier to work with.

To see how I use the data, check out the file in its entirety. How you want to display the data is up to you, but in my template I display the title and content and use the Yoast SEO data to fill out the details in the React Helmet component for SEO.

Add comments from WordPress

If you’re accepting comments on your blog, you’ll need to pull these in as well. You can see how I pull them in in the post query linked above. That filters all the comments associated with a specific post. However, it doesn’t give you a nice nested array detailing which comments belong to which parents. So that’s something you have to do for yourself.

Fortunately, I did all the heavy lifting for you! Check out my Comments component for the details.

In a nutshell:

  1. Sort the comments by those with no parent – those are your top-level comments.
  2. Go through the remaining comments and look for any other comments that have a parent that matches the ID of the top-level comment.
  3. Do this recursively to make sure you get to the bottom of the comment nest and No Children are Left Behind.

Build out the blog index

This is a bit different from the blog posts because it’s actually a defined page that’s using GraphQL data, not a page that’s being built based on nodes of GraphQL data.

Regardless, you’re getting familiar with how GraphQL data works and how to use it, so I’ll just link to some important parts from my pages/blog.jsfile:

Keep going!

This is a quick, basic tutorial for understanding the important parts of pulling in WordPress data to a Gatsby website. There’s obviously a lot more to do, like design and styling, building the homepage, querying for other types of content, etc. But this should get your started. I’ll leave some other helpful tools and resources below:

Using featured images

I don’t use WordPress featured images in my blog posts. However, I do use them in my Projects pages. Pulling in images at load time can be slow and still pings your server for the file instead of using your serverless setup. And pulling them in from the server means that you don’t take advantage of Gatsby Image’s cool tricks, like image sizing, lazy loading, etc.

But! There’s a plugin for that: gatsby-plugin-remote-images

You can see how I use it in my config here, and see how I implement it in my Projects pages – query and implementation.

Automatically rebuild on content change

I published my site to Netlify – highly recommended. It re-builds automatically any time I push to the master branch of my repository. I wanted it to rebuild whenever I published changes in my WordPress API, as well.

In my WordPress theme, I run a function on the save-post action that sends a remote_post to a build hook I created in Netlify. Here’s what that function looks like, including a bit that tells me if the build fails for whatever reason:

public static function action_save_post_trigger_netlify_deploy( $post_id, $post, $update ) {
		$response = wp_remote_post( 'https://api.netlify.com/build_hooks/####' );
		if ( is_wp_error( $response ) ) {
			wp_mail( 'your@email.com', 'Saving post failed to deploy', 'Saving post ' . $post_id . ' failed to trigger a Netlify deploy. Try again!' );

Create a feed

Any good blog should have a feed. Fortunately, gatsby-plugin-feed makes it relatively straightforward. After installing the package, set it up in gatsby-config.js. Here’s how I did it.

Other good plugins

Two other good Gatsby plugins I’d recommend:

Still to-do

I still have a number of items to work out:

  1. Allow people to reply to a comment. Right now you can only post a top-level comment on a blog post.
  2. Pull in post images into my Gatsby site at build time. I can do it with featured images, but not in-post images. So that’s not super performant, as discussed above. This requires getting the Gutenberg block data included as a nice array or object in the REST API response instead of a giant string. There’s an existing solution for that, but I haven’t delved into it.
  3. Build a post preview component that loads draft data from the REST API at runtime. Right now I can only preview content on my WordPress front-end. The design is similar (it’s what I based my Gatsby site design off of), but, again, it’s not ideal. I’d like to be able to actually preview the content on my Gatsby site.

And that’s all!

I hope you found this brief tutorial helpful for creating a Gatsby JS site using WordPress as a CMS.

Leave a Reply

Your email address will not be published. Required fields are marked *

3 Comments on "Creating a Gatsby Front-End with a WordPress CMS"

  1. Kevin

    August 12, 2020

    A nice read of a practical use of WordPress + Gatsby. Seems to be the way forward for most standard WP builds now anyway, and with ever-growing plugin library at Gatsby, makes for exciting times!

  2. Stephen Petrey

    April 19, 2020

    Oh boy, thank you. Recently migrated my front-end to Gatsby as well. I’ve been searching for a drop-in RSS generation example like this! Extra thanks for sharing your gatsby-config.js ✌️

    1. Raquel Smith

      April 20, 2020

      Glad you found it helpful!!

  • About
  • Projects
  • Bookshelf
  • Blog
  • Github@raquelmsmith
  • LinkedIn@raquelmsmith
  • Emailhello@raquelmsmith.com