We all know that a headless CMS can deliver your content through an API directly to where you need it. Because of the headless approach the content can be used on any platform and technology you can think of, and is therefore a powerful option for mobile and web developers.
In this article we’ll cover the integration and querying data using Strapi as a headless CMS to handle the backend and Gatsby for the front end. Before jumping to how to integrate Strapi with Gatsby, let’s first understand what Strapi is?
What is Strapi?
Strapi is a free and open-source headless CMS delivering your content anywhere you need.
- Keep control over your data. With Strapi, you know where your data is stored, and you keep full control at all times.
- Self-hosted. You can host and scale Strapi projects the way you want. You can choose any hosting platform you want: AWS, Render, Netlify, Heroku, a VPS, or a dedicated server. You can scale as you grow, 100% independent.
- Database agnostic. You can choose the database you prefer. Strapi works with SQL & NoSQL databases: MongoDB, PostgreSQL, MySQL, MariaDB, and SQLite.
- Customizable. You can quickly build your logic by fully customizing APIs, routes, or plugins to fit your needs perfectly.
You can easily retrieve data via GraphQL by adding it from Strapi plugins.
Why Strapi + Gatsby?
Using a static site generator brings a lot of advantages: Performance, security, lower cost of scaling but also an excellent developer experience. Gatsby brings enormous benefits to content creators and developers by solving many of the challenges with the headless approach.
Strapi provides a perfect solution as a source for Gatsby’s static markup generation. Whether building a static site or a more dynamic app/website Strapi has you covered with its flexibility of content types, plugins, and customization. Chris, GatsbyJS developer.
Let’s make this in action by building a blog using Gatsby and Strapi as a headless CMS.
Install Strapi and Create a new project
1yarn create strapi-app my-project --quickstart
Create an Administrator user
Navigate to http://localhost:1337/admin
Complete the form to create the first Administrator user. Now you can create the content types you need. Once the installation is completed, you can start on your frontend.
Create a Gatsby site
Create a basic Gatsby site using the Gatsby CLI
1gatsby new gatsby-app
You need to configure Gatsby to communicate with your Strapi.
1yarn add gatsby-source-strapi
Add the gatsby-source-strapi to the plugins section in the gatsby-config.js file:
1{2 resolve: "gatsby-source-strapi",3 options: {4 apiURL: "http://localhost:1337",5// list of the content type you created on Strapi, Ex:6 contentTypes:7[ "post", "category", "author" ],8// If using single types place them in this array.9// singleTypes: [`home-page`, `contact`],10 queryLimit: 1000,11 },12},
Now you can send requests to Strapi to fetch all the data you want from the content types.
Be sure that you activated the find, findOne permission for the content type. Lets use the content types we declare in the gatsby-config.js
- Post
- Category
- Author
Example Request:
1query {2 allStrapiPost {3 edges {4 node {5 id6 title7 content8 }9 }10 }11}
Since you can send requests to Strapi, let’s generate pages for each of the posts, categories, and authors. We’ll use the createPages API.
In createPages add the following code to your gatsby.node.js file:
1exports.createPages = ({ actions, graphql }) => {2 const { createPage } = actions3graphql(`4 {5 allStrapiPost {6 edges {7 node {8 id9 title10 }11 }12 }13 }14 `15 ).then(({ data, errors }) => {16 if (errors) {17 return Promise.reject(errors)18 }1920 const { edges } = data.allStrapiPost2122 edges.forEach(({ node }) => {23 createPage({24 path: `/posts/${node.title}`,25 component: path.resolve(`./src/templates/post.js`),26 context: {27 id: node.id,28 },29 })30 })31 })32graphql(`33 {34 allStrapiCategory {35 edges {36 node {37 id38 name39 }40 }41 }42 }43 `44 ).then(({ data, errors }) => {45 if (errors) {46 return Promise.reject(errors)47 }4849 const { edges } = data.allStrapiCategory5051 edges.forEach(({ node }) => {52 createPage({53 path: `/categories/${node.name}`,54 component: path.resolve(`./src/templates/category.js`),55 context: {56 id: node.id,57 },58 })59 })60 })61graphql(`62 {63 allStrapiAuthor {64 edges {65 node {66 id67 name68 }69 }70 }71 }72 `73 ).then(({ data, errors }) => {74 if (errors) {75 return Promise.reject(errors)76 }7778 const { edges } = data.allStrapiAuthor7980 edges.forEach(({ node }) => {81 createPage({82 path: `/authors/${node.name}`,83 component: path.resolve(`./src/templates/author.js`),84 context: {85 id: node.id,86 },87 })88 })89 })9091 })92}
We are fetching all posts, authors, and categories to generate pages for each of them.
Create a ./src/templates/post.js file that will display the content of each one of your post:
1import React from 'react'2import { graphql } from 'gatsby'34export const query = graphql`5 query Post($name: String!) {6 posts: strapiPost(title: { eq: $title }) {7 id8 name9 content10 category {11 id12 name13 }14 author {15 id16 name17 }18 }19 }20`2122const Post = ({ data }) => {23 const posts = data.posts24 const category = data.posts.category25 const author = data.posts.author2627 return (28 <div>29 <h1>{post.title}</h1>30 <ul>31 <li>{category.name}</li>32 <li>{author.name}</li>33 </ul>34 <p>{post.content}</p>35 </div>36 )37}3839export default Post
You can find your post posts by browsing:
http://localhost:8000/posts/title-of-post.
Create a ./src/templates/category.js file that will display the content of each one of your category:
1import React from 'react';2import { graphql, Link } from 'gatsby';34export const query = graphql`5 query Category($name: String!) {6 category: strapiCategory(name: { eq: $name }) {7 name8 posts {9 id10 name11 }12 }13 }14`;1516const Category = ({ data }) => {17 const posts = data.category.posts;18 const category = data.category.name;1920 return (21 <div>22 <h1>{category}</h1>23 <ul>24 {posts.map(post => {25 return (26 <Link to={`/posts/${post.title}`} />{post.title}</Link>27)28 })}29 </ul>30 </div>31 );32};3334export default Category;
You can find your restaurant categories by browsing: http://localhost:8000/category/name-of-category.
Feel free to do the same for your authors!
Awesome! You can see the posts, and they are listed depending on the category and the author now.