Strapi Getting Started with Gatsby
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
yarn 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
gatsby new gatsby-app
You need to configure Gatsby to communicate with your Strapi.
yarn add gatsby-source-strapi
Add the gatsby-source-strapi to the plugins section in the gatsby-config.js file:
{
resolve: "gatsby-source-strapi",
options: {
apiURL: "http://localhost:1337",
// list of the content type you created on Strapi, Ex:
contentTypes:
[ "post", "category", "author" ],
// If using single types place them in this array.
// singleTypes: [`home-page`, `contact`],
queryLimit: 1000,
},
},
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:
query {
allStrapiPost {
edges {
node {
id
title
content
}
}
}
}
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:
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions
graphql(`
{
allStrapiPost {
edges {
node {
id
title
}
}
}
}
`
).then(({ data, errors }) => {
if (errors) {
return Promise.reject(errors)
}
const { edges } = data.allStrapiPost
edges.forEach(({ node }) => {
createPage({
path: `/posts/${node.title}`,
component: path.resolve(`./src/templates/post.js`),
context: {
id: node.id,
},
})
})
})
graphql(`
{
allStrapiCategory {
edges {
node {
id
name
}
}
}
}
`
).then(({ data, errors }) => {
if (errors) {
return Promise.reject(errors)
}
const { edges } = data.allStrapiCategory
edges.forEach(({ node }) => {
createPage({
path: `/categories/${node.name}`,
component: path.resolve(`./src/templates/category.js`),
context: {
id: node.id,
},
})
})
})
graphql(`
{
allStrapiAuthor {
edges {
node {
id
name
}
}
}
}
`
).then(({ data, errors }) => {
if (errors) {
return Promise.reject(errors)
}
const { edges } = data.allStrapiAuthor
edges.forEach(({ node }) => {
createPage({
path: `/authors/${node.name}`,
component: path.resolve(`./src/templates/author.js`),
context: {
id: node.id,
},
})
})
})
})
}
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:
import React from 'react'
import { graphql } from 'gatsby'
export const query = graphql`
query Post($name: String!) {
posts: strapiPost(title: { eq: $title }) {
id
name
content
category {
id
name
}
author {
id
name
}
}
}
`
const Post = ({ data }) => {
const posts = data.posts
const category = data.posts.category
const author = data.posts.author
return (
<div>
<h1>{post.title}</h1>
<ul>
<li>{category.name}</li>
<li>{author.name}</li>
</ul>
<p>{post.content}</p>
</div>
)
}
export 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:
import React from 'react';
import { graphql, Link } from 'gatsby';
export const query = graphql`
query Category($name: String!) {
category: strapiCategory(name: { eq: $name }) {
name
posts {
id
name
}
}
}
`;
const Category = ({ data }) => {
const posts = data.category.posts;
const category = data.category.name;
return (
<div>
<h1>{category}</h1>
<ul>
{posts.map(post => {
return (
<Link to={`/posts/${post.title}`} />{post.title}</Link>
)
})}
</ul>
</div>
);
};
export 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.