Content Management with Gatsby, Contentful & Netlify


/ 18/02/2019

Gatsby, Contentful, Netlify — The Triple Threat For Content Management Success

Gatsby, Contentful & Netlify for the win!
I’ve been using Gatsby for the better part of 6 months and it’s quickly become my go-to for building static sites. The advantages are huge. You get:
A lot of configuration and boilerplate done out of the box.
Speed, SEO and performance optimizations.
A great community, great docs and a growing plugin ecosystem.
And my personal favorite — getting to write all the React & GraphQL code I want.
It’s been a great developer experience, to say the least. However, when building static sites, one of the major concerns in choosing a tool is how content gets updated on the site. Lots of older platforms have solved this one way or another, Wordpress being the most popular of them, but using the triple threat of Gatsby, Netlify, and Contentful, we can build a pretty good alternative to the traditional CMS tools out there while retaining our SEO compatibility.
This article will show you how you can set up a system for managing content on any page of your Gatsby site. In our case, we’ll be using Gatsby’s powerful gatsby-node API to pull in content from Contentful and to dynamically generate pages. You can also use Contentful data on any existing page via the provided graphql queries.
This is going to be a long one, so stretch your legs, grab a coffee or pick-me-up of your choice and let’s begin.
You’ll need the gatsby-cli tool to get started. Run npm i -g gatsby in your terminal and once that has run, create a new project with
$ gatsby new gatsby-contentul-blog
This will create a new Gatsby project in a folder called gatsby-contentful-blog. cd into the new project and run gatsby develop. Now you have the default Gatsby starter homepage:
Open up the project in your favorite text editor and navigate to the pages folder. Let's tweak some of the content in the index.js: (You can just copy and paste this in)
import React from "react"; import { Link } from "gatsby"; import Layout from "../components/layout"; import Image from "../components/image"; import SEO from "../components/seo"; import "./index.css"; const IndexPage = () => ( <Layout> <SEO title='Home' keywords={[`gatsby`, `application`, `react`]} /> <div className='home'> <h1>Hello There</h1> <p>Welcome my awesome blog</p> <div> <div style={{ maxWidth: `300px`, margin: '0 auto 1.45rem', }} > <Image /> </div> </div> <Link to='/blogposts/'>View all posts</Link> </div> </Layout> ); export default IndexPage;
Next, find page-2.js and change the filename to blogposts.js. Gatsby uses the name of any file in the pages folder as a route name and will make the exported React component available on said route. This means we now have a /blogposts route. We'll come back to this file later but in the meantime, let's also change a few values in the gatsby-config.js file. This file sits in the project root.
siteMetadata: { title: `My Awesome Blog`, description: `An awesome blog displaying my awesome posts.`, author: `YOUR_NAME`, },
Great! We now have our basic site set up. So we’ll go to the Contentful website and create a new account. It’s pretty painless and you should be set up in no time. By default, they provide an example space but let’s create a fresh one for the project.
Open up the sidebar and click on Create Space. Choose the free option and give your space any name. I’ll call mine gatsby-blog. Select the empty space option, click Proceed to confirmation, and confirm your options.
After confirming, on the dashboard, click either the “Create Content Type” button or the “Content Model” button in the header and fill in the form that appears. Let’s call the content type Blog Post and leave the API Identifier as is. Enter any description you’d like.
After creating the content type, we’ll start to add some fields to it “A field” is a building block for our content. If you have a blog post for instance, a few fields could be the title, the body, the tags and an image. This will generate a form that you’ll fill later on when we start to create actual blog posts. Follow the next steps to create a title field.
Click on the Add Field button to the right of the dashboard.
Select Text as the type of field you want.
In the form on the next screen, enter title as the name, then click on create.
Add another text field called body, but after selecting Text, select Long ext from the radio button on the screen below.
Add another field. Select Media as the type instead of Text and call it image.
Add a tags field by selecting Text as the type. Give it tags as a name, and then select the list option on the screen below since we will be storing a list of tags in this field.
Lastly, create a slug field. Start by selecting Text as the type and call it slug. This time, instead of clicking Create as above, click on Create and Configure. On the next screen go to the Appearance tab and select slug as the way the field should be displayed. Also, in the Validations tab select unique field to be sure that no two blog posts have the same slugs
Your content model should now look like this:
A content model is like a schema that our actual content will follow. You can create all types of models such as case studies, blog posts, product data, page content and so on.
Save your changes and click on the Content button at the top of the page and select Add Blog Post. I’m going to add three posts with placeholder data, feel free to add as many as you’d like. For images, you can grab some free, open license ones from Notice how the slug field gets auto-generated as you enter the title? This will come in handy later.
Awesome! That was a lot but we’re halfway there…
At this point we have our first couple of blog posts and it’s time to bring them into our Gatsby site. For this, we’ll depend on Gatsby’s awesome GraphQL API for pulling in the data. Let’s work on that next.
Go to your settings in Contentful and click on the API Keys option in the dropdown menu. Create a new API Key and keep the details close by.
Back in your terminal, install the Gatsby plugin we need to start pulling in our Contentful data.
$ yarn add gatsby-source-contentful
We’ll be using Contentful’s Content Delivery API since we want to retrieve published data only, so be sure to grab the Content Delivery API key and not the Content Preview API key.
In your gatsby-config.js file, add the configuration object to the plugins array:
plugins: [ ... { resolve: `gatsby-source-contentful`, options: { spaceId: `YOUR_SPACE_ID`, accessToken: `YOUR_CONTENT_DELIVERY_API_KEY` } } ],
You should restart your development server again at this point for the new configs to kick in. When the server restarts, gatsby-source-contentful's GraphQL queries will be available to use.
We can easily test if everything is working by using the GraphiQL playground that Gatsby provides for us. Open http://localhost:8000/___graphql in your browser and run the query below by pasting it into the left window on the page. The query name is allContentfulBlogPost because our content model is called Blog Post. If we had called it Product or Case Study, then the query made available to us would have been allContentfulProduct or allContentfulCaseStudy.
{ allContentfulBlogPost { edges { node { id slug title tags image { file { url } } } } } }
The gatsby-source-contentful plugin handles all the behind the scenes fetching from the Contentful API using the keys we provided in the gatsby-config file. It then makes a semantically named GraphQL query available to us.
If it all works, you should see the content you added in the results window to the right of the GraphiQL window in JSON format.
Now that we have connected our Gatsby blog with our Contentful data, we can start building the pages for the blog. Gatsby provides us with a file called gatsby-node.js. This file can be used to dynamically add pages to your site. When Gatsby runs, it will look at the code here and create any pages you tell it to. In the gatsby-node.js file, let's place the following code:
const path = require(`path`); const slash = require(`slash`); exports.createPages = ({ graphql, actions }) => { const { createPage } = actions; // we use the provided allContentfulBlogPost query to fetch the data from Contentful return graphql( ` { allContentfulBlogPost { edges { node { id slug } } } } ` ).then(result => { if (result.errors) { console.log("Error retrieving contentful data", result.errors); } // Resolve the paths to our template const blogPostTemplate = path.resolve("./src/templates/blogpost.js"); // Then for each result we create a page. => { createPage({ path: `/blogpost/${edge.node.slug}/`, component: slash(blogPostTemplate), context: { slug: edge.node.slug, id: } }); }); }) .catch(error => { console.log("Error retrieving contentful data", error); }); };
This module exports a function called createPages. This function has two parameters, Graphql, and an actions object. We extract the createPage action then call the same Graphql query we ran in the GraphQL playground earlier. We take this result and for each result (each blog post) we call the createPage function. This function accepts a config object which Gatsby reads when rendering the page. We set the path equal to the concatenated string "/blogpost" plus the slug. Notice that we also reference a template file at ./src/templates/blogpost.js, not to worry, we'll create that file soon.

Content Management with Gatsby, Contentful & Netlify

Babs Craig /


Gatsby, Contentful, Netlify — The Triple Threat For Content Management Success

Focus Management with React Native on TV Plaforms

Guillermo Velásquez /


Helping frontend / React engineers prepare for interviews with mock interviews

How to set up a Monorepo with React Native You.I and Yarn Workspaces

Andrei Calazans /


In order to simplify dependency management, code reuse, and collaboration across teams, many projects have sought out to use the Monorepo structure.