Turbocharge Your Gatsby Site with GraphCMS
Static site generators like Gatsby have surged in popularity recently, allowing developers to create lightning-fast websites with React while retaining the benefits of static HTML files. But Gatsby‘s true superpower is its vast plugin ecosystem and ability to pull data from any source.
In this guide, we‘ll walk through integrating Gatsby with GraphCMS, a headless CMS that enables you to define structured content models and consume the data via a flexible GraphQL API. GraphCMS is an excellent pairing with Gatsby, giving you a friendly interface for content management while allowing developers to query data in a format that fits seamlessly into Gatsby‘s data layer.
Whether you‘re building a personal blog, a company marketing site, or a high-powered web app, this potent combination can help you build for the web faster. Let‘s dive in!
Getting Started
Before we begin, you‘ll need:
- Basic familiarity with Gatsby and React
- A Gatsby site to work with (starting with the default starter is fine)
- A free GraphCMS account
Got those ready? Great, let‘s set up GraphCMS.
Defining Your Content Model in GraphCMS
GraphCMS allows you to define your content models in a flexible way to fit your needs. In this example, we‘ll create a simple "Blog Post" model.
After creating a new project in GraphCMS, head to the "Schema" tab in the sidebar. Click "Create Model" and name it "Blog Post".
Next, add some fields to the model. Let‘s go with:
- Title (single line text)
- Slug (single line text)
- Excerpt (multi line text)
- Content (multi line text, markdown enabled)
- Cover Image (asset, image)
You can of course customize these to your liking and even link to other content models. The beauty of a headless CMS is that your content is decoupled from your presentation, so you have complete flexibility.
With the model defined, go ahead and create a few sample blog posts in the "Content" tab. Let‘s move on to configuring the API.
Configuring GraphCMS API Permissions
In order for Gatsby to query your GraphCMS data, you need to enable read access to the published content. In your project‘s settings, navigate to "API Access" and scroll down to "Public API Permissions".
Set all of the models you want exposed to "Read". For our example, we just need to enable read access for the "Blog Post" model.
While you‘re in the API settings, scroll a bit further down and copy your "Content API" endpoint. You‘ll need this to configure the Gatsby plugin. It should look something like:
https://api-us-west-2.graphcms.com/v2/your-project-id/master
With the GraphCMS side taken care of, let‘s jump into Gatsby!
Pulling GraphCMS Data into Gatsby
Gatsby has a powerful plugin called gatsby-source-graphql
that allows you to query data from a GraphQL API and bring it into Gatsby‘s data layer. Let‘s set it up.
First, install the plugin:
npm install gatsby-source-graphql
Then, add it to your gatsby-config.js
:
module.exports = {
plugins: [
{
resolve: ‘gatsby-source-graphql‘,
options: {
typeName: ‘GraphCMS‘,
fieldName: ‘graphcms‘,
url: ‘YOUR_GRAPHCMS_ENDPOINT‘,
},
},
],
}
Be sure to replace YOUR_GRAPHCMS_ENDPOINT
with the API URL you copied from GraphCMS in the previous step.
The typeName
option determines how you‘ll refer to this data source in your GraphQL queries (in this case GraphCMS
). The fieldName
option will be the name of the root query field for this data source (graphcms
).
With the plugin configured, restart your development server with gatsby develop
. GraphCMS data is now available in Gatsby‘s data layer. Time to query it!
Querying GraphCMS Data in GraphiQL
Gatsby ships with a built-in GraphQL IDE called GraphiQL (pronounced "graphical"). It provides an interactive environment to explore your data and craft queries. Access it by navigating to http://localhost:8000/___graphql
while your Gatsby development server is running.
In the GraphiQL Explorer pane on the left, you should see your GraphCMS data source listed as graphcms
. Expand it and you‘ll see the available query fields based on your GraphCMS schema. For our "Blog Post" model, it should look something like:
{
graphcms {
blogPosts {
title
slug
excerpt
content
coverImage {
url
}
}
}
}
Click the "Play" button to execute the query and see the result in the response pane on the right. GraphiQL is a great way to test queries before adding them to your Gatsby pages and components.
Displaying GraphCMS Data in Pages & Components
Now for the fun part – displaying your GraphCMS data in your Gatsby site!
Gatsby uses a mesh of plugins, GraphQL queries, and React components to build pages. The GraphQL query tells Gatsby what data the page or component needs, then that data is passed into the React component as props to be rendered into HTML.
Let‘s build an index page that lists our blog posts. In src/pages/index.js
:
import React from ‘react‘
import { graphql, Link } from ‘gatsby‘
const IndexPage = ({ data }) => {
const { blogPosts } = data.graphcms
return (
<div>
<h1>Blog Posts</h1>
{blogPosts.map(post => (
<div key={post.slug}>
<img src={post.coverImage.url} alt={post.title} />
<h2>
<Link to={`/${post.slug}`}>{post.title}</Link>
</h2>
<p>{post.excerpt}</p>
</div>
))}
</div>
)
}
export const query = graphql`
{
graphcms {
blogPosts {
title
slug
excerpt
coverImage {
url
}
}
}
}
`
export default IndexPage
The graphql
tagged template literal contains our GraphQL query that fetches the list of blog posts with the fields we want to display. This query is executed at build time and the result is passed into the IndexPage
component as the data
prop.
We destructure the blogPosts
array from data.graphcms
, then use map()
to loop through the posts and render each one‘s cover image, title (wrapped in a link to the post‘s individual page), and excerpt.
To generate pages for each individual blog post, we can use Gatsby‘s createPages
Node API in gatsby-node.js
:
const path = require(‘path‘)
exports.createPages = async ({ actions: { createPage }, graphql }) => {
const results = await graphql(`
{
graphcms {
blogPosts {
slug
}
}
}
`)
results.data.graphcms.blogPosts.forEach(post => {
createPage({
path: `/${post.slug}`,
component: path.resolve(‘./src/templates/blog-post.js‘),
context: {
slug: post.slug,
},
})
})
}
This queries GraphCMS for just the slug
field of each blog post, then loops through the results and uses createPage
to dynamically generate a page for each post at its slug URL. It uses a page template component (blog-post.js
) and passes the slug
into the page query as variables.
Here‘s what the blog-post.js
template might look like:
import React from ‘react‘
import { graphql } from ‘gatsby‘
const BlogPostTemplate = ({ data }) => {
const { blogPost } = data.graphcms
return (
<div>
<img src={blogPost.coverImage.url} alt={blogPost.title} />
<h1>{blogPost.title}</h1>
<div dangerouslySetInnerHTML={{ __html: blogPost.content.html }} />
</div>
)
}
export const query = graphql`
query BlogPostQuery($slug: String!) {
graphcms {
blogPost(where: { slug: $slug }) {
title
content {
html
}
coverImage {
url
}
}
}
}
`
export default BlogPostTemplate
The page query uses a query variable $slug
(passed in from createPage
in gatsby-node.js
) to fetch just the GraphCMS blog post that matches that slug
value. The blogPost
object is destructured from data.graphcms
and its fields are rendered into the page template.
Note the content
field is queried as html
. This is because GraphCMS provides a Markdown to HTML transformation out of the box. The rendered HTML is output using React‘s dangerouslySetInnerHTML
.
And there you have it! A Gatsby site pulling blog post content from GraphCMS. Of course, this just scratches the surface of what‘s possible with Gatsby and GraphCMS. You can create more complex content models, query relationships between models, filter and sort your content, generate category and tag pages, and so much more.
Tips & Best Practices
As you build out your Gatsby + GraphCMS site, here are a few tips to keep in mind:
- Use clear, descriptive names for your GraphCMS models and fields. This will make your GraphQL queries more readable and maintainable.
- Take advantage of GraphCMS‘s built-in rich text fields and transformations to easily render formatted content.
- Use Gatsby‘s
createPages
API to dynamically generate pages from your GraphCMS content, whether that‘s blog posts, product pages, or something else. - Keep your GraphQL queries concise by only requesting the fields you need for that particular page or component. This helps avoid overfetching data and keeps your site lean.
- Use GraphQL fragments to share query logic across multiple queries and components.
- Structure your Gatsby project with a clear separation of concerns. Put GraphQL queries in their associated pages or components, use page templates, and keep your
gatsby-node.js
file clean and focused on page generation.
Gatsby + GraphCMS in the Wild
Wondering what kinds of sites are being built with Gatsby and GraphCMS? Here are a few real-world examples to inspire you:
- Studious: A coding education platform using GraphCMS to manage their curriculum content.
- StabPay: A fintech startup using Gatsby + GraphCMS for their marketing site, leveraging GraphCMS‘s localization features to serve content in multiple languages.
- The Rick and Morty Wiki: A fan-made wiki site for the show "Rick and Morty," built with Gatsby and pulling character and episode data from GraphCMS.
The possibilities are endless! Whether you‘re building a personal blog, a corporate site, or a complex web app, Gatsby and GraphCMS provide a highly performant and flexible stack.
Wrapping Up
In this guide, we‘ve walked through the process of integrating GraphCMS content into a Gatsby site, from defining content models to querying data to generating pages. The combination of Gatsby‘s fast, React-based architecture and GraphCMS‘s flexible content management capabilities make them a powerful duo for building modern websites.
But don‘t just take my word for it – dive in and try it yourself! Experiment with different content models, build out more pages and components, and see how Gatsby and GraphCMS can streamline your web development workflow.
Happy coding!