Strapi Getting Started with Gatsby

Oussama Benidir
March 17th, 2021 · 2 min read

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 id
6 title
7 content
8 }
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 } = actions
3graphql(`
4 {
5 allStrapiPost {
6 edges {
7 node {
8 id
9 title
10 }
11 }
12 }
13 }
14 `
15 ).then(({ data, errors }) => {
16 if (errors) {
17 return Promise.reject(errors)
18 }
19
20 const { edges } = data.allStrapiPost
21
22 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 id
38 name
39 }
40 }
41 }
42 }
43 `
44 ).then(({ data, errors }) => {
45 if (errors) {
46 return Promise.reject(errors)
47 }
48
49 const { edges } = data.allStrapiCategory
50
51 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 id
67 name
68 }
69 }
70 }
71 }
72 `
73 ).then(({ data, errors }) => {
74 if (errors) {
75 return Promise.reject(errors)
76 }
77
78 const { edges } = data.allStrapiAuthor
79
80 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 })
90
91 })
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'
3
4export const query = graphql`
5 query Post($name: String!) {
6 posts: strapiPost(title: { eq: $title }) {
7 id
8 name
9 content
10 category {
11 id
12 name
13 }
14 author {
15 id
16 name
17 }
18 }
19 }
20`
21
22const Post = ({ data }) => {
23 const posts = data.posts
24 const category = data.posts.category
25 const author = data.posts.author
26
27 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}
38
39export 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';
3
4export const query = graphql`
5 query Category($name: String!) {
6 category: strapiCategory(name: { eq: $name }) {
7 name
8 posts {
9 id
10 name
11 }
12 }
13 }
14`;
15
16const Category = ({ data }) => {
17 const posts = data.category.posts;
18 const category = data.category.name;
19
20 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};
33
34export 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.

More articles from Obytes

How we used Cloudflare Argo Tunnels + Access to replace a VPN

An alternative to a VPN provided by Cloudflare, and how we set it up on AWS using Terraform

March 15th, 2021 · 4 min read

Why you should start using TailwindCSS for your next project

Everyone agrees that CSS is easy in the first start but as you go in deeper it becomes a lot messy and complicated over time. Remember how…

March 2nd, 2021 · 3 min read

ABOUT US

Our mission and ambition is to challenge the status quo, by doing things differently we nurture our love for craft and technology allowing us to create the unexpected.