📝 Building a Static Blog using Gatsby and Strapi

18 January 2018

REVISED AND UPDATED: 15 JUNE 2019

A static website contains Web pages with fixed content. Technically, it is a simple list of HTML files, which displays the same information to every visitor. Unlike dynamic websites, they do not require any back-end programming or database. Publishing a static website is easy: the files are uploaded on a simple Web server or storage provider. The two main advantages of static websites are security and speed: there is no database so it can not be hacked and there is no need to render a page for each request, which makes Web browsing faster.

To make their creation easier, numerous open-source static websites generators are available: Jekyll, Hugo, Hexo, etc. Most of the time, the content is managed through static (ideally Markdown) files or a Content API. Then, the generator requests the content, injects it in templates defined by the developer and generates a bunch of HTML files.

Progressive Web Apps (PWA) are web applications, highly based on JavaScript, and are reliable, fast and engaging. Since they make web browsing much faster and offer a better user experience, PWA has become the default way to build Web interfaces. Thus, many amazing front-end frameworks appeared over the last couple years: Angular, React and more recently, Vue.

Gatsby: when static websites meet Progressive Web Apps

Both static websites and PWAs have strong advantages which make us crave for a way to use them together in the same project! Luckily, we have tools that bridge the gap between them and the one we recently heard of is definitely Gatsby. So, we decided to give you a complete example of how to get started with Gatsby. A static website needs a source of content: in this example, we will deliver it using an API built with Strapi.

What is Gatsby?

Gatsby is a blazing-fast website framework for React. It allows developers to build React based websites within minutes. Whether you want to develop a blog or a corporate website, Gatsby will fill your needs.

Because it is based on React, the website pages are never reloaded which makes the generated website super fast. A large set of plugins is available to allowing developers to save time coding. For example, plugins exist to get data from any source (Markdown files, CMS, etc.). Gatsby is strongly based on the "node" interface, which is the center of Gatsby's data system.

What is Strapi?

Strapi is an open source Headless CMS Front-End Developers Love. It's more than a Node.js Framework and more than a Headless CMS, it saves weeks of API development time, and allows easy long-term content management through a beautiful administration panel anyone can use.

It is entirely customisable and extensible, thanks to the plugin system.

Learn Gatsbyjs with Strapi Headless CMS Video Tutorial Series

Please follow along watching the videos below and reading the text. You can watch just the videos or read just the text, but you will get the most from this tutorial by watching and reading both. The videos are designed to be used together with this article.

The videos follow the exact sequence of this article. The videos contain additional information and additional configuration details for a few sections. However, for intermediate to advanced users this article will be sufficient to get oriented and started building Strapi powered Gatsby projects.

Using the --quickstart flag creates a full Strapi project and automatically starts the server and opens up a tab in your browser.

(If you leave off --quickstart. Strapi allows you to configure the project according to your needs, Strapi will ask you some questions about your preferences. In this case, reply to each of them or press enter to keep the default values. If you choose a different database than SQLite, you will need to separately install that database onto your system and have it running in the background.)

In this example, we are using Strapi. Obviously, we are going to need a source plugin for Strapi APIs. Good news: we built it for you!

Let's install it:

Path: blog/

npm install --save gatsby-source-strapi

This plugin needs to be configured. Replace the content of gatsby-config.js with:

NOTE: Please understand that the apiURL:, e.g. http://localhost:1337 does NOT have a trailing slash. This will create issues, as a slash is added by other code in the plugin.

Path: blog/gatsby-config.js

Allow access to User

Remember, when we created the content type we created a relation between User and Articles.

Like Article,User, link is likewise, by default, restricted. But Gatsby needs access, so to allow access, visit the Auth and Permissions section for Public role, click on Public, select the User - find action and save. After saving; Gatsby will have access to all the necessary content types managed by Strapi (for this tutorial).

Restart Strapi from the command line, inside the cms folder - first by Ctrl+ C to stop the server; and then typing strapi develop, to restart it.

Next, restart the Strapi server to allow Gatsby to register these updates, the next time you restart Gatsby.

6. Create our Index Page

Articles list

First, we want to display the list of articles. To do so, add the following content in the existing home page file:

Path: blog/src/pages/index.js

What are we doing here?

At the end of the file, we export pageQuery, a GraphQL query which requests the entire list of articles. As you can see, we require only the id, title and content fields, thanks to the precise GraphQL query language.

Then, we pass the { data } destructured object as parameter of IndexPage and loop on its allStrapiArticle object to display the data.

Tip: generate your GraphQL query in seconds!

Gatsby includes a useful GraphiQL interface. It makes GraphQL queries development way easier and intuitive. Take look at it and try to create some queries.

Adding images

To add images, we will need to import Img from package gatsby-image installed by default. Replace the content of blog/src/pages/index.js with the following :

In order to do this, first create a folder called templates in your src directory. Then within templates create a file called article.js.

Path: blog/src/templates/article.js

That looks fine, but at this point, Gatsby does not know when this template should be displayed. Each article needs a specific URL. So, we are going to inform Gatsby about the new URLs we need thanks to the createPage function.

First, we are going to code a new function called makeRequest to execute the GraphQL request. Then, we export a function named createPages in which we get the list of articles and create a page for each of them. Here is the result:

Path: blog/gatsby-node.js

Restart the Gatsby server.

From now on, you should be able to visit the detail page by clicking on URLs displayed on the homepage.

If your browser window open at the Heroku URL, congratulations. If not, please review the documentation and the video for additional details.

Set-up Administrator and User Roles

Your browser should have opened back up to the Strapi Welcome page. Click on the /admin link to enter the Administrator User.

Complete the form for the first Administrator User.

Click on Users located under CONTENT TYPES in the left-hand menu.

Click the blue + Add New User button in the top right corner.

Next, complete the Username, Email, and Password fields.

Select ON for the Confirmed toggle field.

To the right, under Role, select Authenticated.

Configure the WYSIWYG Editor View

When you locally created the Article content, you checked WSYISWG as a setting for the content field. When you created a new install for Heroku with PostreSQL, you lost these settings. You will now reset these settings:
- Click on Content Manager in the left-hand menu
- Then under Content Types, click on Article
- Click the Edit View (Settings) tab and then under LAYOUT - Displayed Fields - click and highlight the content field.
- Scroll down and toggle ON for Display as WYSIWYG

Continue to adding content below.

Insert some entries

Articles now need to be added again to the Production installation of Strapi. Add some articles in the database. To do so, follow these instructions:

From you Dashboard, click on the Articles content type in the left-hand menu.

9A. Configure again Permissions

You have to allow access through the API under Roles & Permission from your Strapi Dashboard.

You have already set these permissions on your local Dev environment. But these settings need to be set again for Heroku as these settings are saved to a database and the Heroku PostgreSQL database is different than your local Dev environment.

10. Set-up Cloudinary & Netlify Predeploy

At this point, when you upload images to Strapi on Heroku, the images are not permanently saved. The reason is because they are saved to a temporary cache which gets deleted whenever Heroku goes to sleep.

Therefore, you will want to use a 3rd party service to upload to and then serve your images from. This tutorial continues with Cloudinary.

In order to easily push your Gatsby site to Netlify, you have to install and login to Netlify using the Netlify CLI:

From your command line:

npm install netlify-cli -g
netlify login

Press the Authorize button and close the tab or window.

Netlify is now set-up on your computer. It's time to initialize your project (Please pay close attention to the build command and directory):

Path: ./blog/

netlify init
? What would you like to do? + Create & configure a new site
? Site name (optional):
? Team: YOUR NAME HERE
Site Created
Admin url: https://app.netlify.com/sites/SITE-NAME
Site url: https://SITE-NAME.netlify.com
Site ID: YOUR-UNIQUE-SITE-ID
? Your build command (hugo/yarn run build/etc): gatsby build
? Directory to deploy (blank for current dir): public
? No netlify.toml detected. Would you like to create one with these build settings? Yes
Creating Netlify Github Notification Hooks...
Netlify Notification Hooks configured!
Netlify CI/CD Configured!
The site is now configured to automatically deploy from github branches & pull requests
Next steps:
git push Push to your git repository to trigger new site builds
netlify open Open the Netlify adlin URL of your site

A last git add, git commit and git push are needed in order to finish the connection between your github and Netlify. Then open your Netlify Deployment Console.

Modify the model for the Article Content Type

The following is the new Article.js file. This file now has additional code that use the variable withe the netlify webhook. Whenever this Content Type is creates a new instance, updates one or deletes one of the content types, it will fire a Post request to Netlify using the Webhook URL.

Install Axios

Your new code changes require the installation of an npm package called, axios.

From you command line:

Path: ./cms

npm i axios --save

Commit and Push to Heroku and Update Netlify

You will now need to add, commit and push your changes in the project. These changes were made in the Strapi files. Doing this will automatically fire a Post request to Netlify, which will update Netlify automatically.

Webhooks configured

After Netlify has had a moment to issue the command to rebuild and has done so, you will be able to login into your Heroku based Strapi project and make updates which automatically update Netlify.

Additional Content Types

In this example tutorial we created one Content Type called, article. You will need to update the model file (as above) for every additional Content Type you create for your project AND which should trigger a Gatsby rebuild.

If you take a look at your project, you will see that the Markdown is now properly transforming into HTML. However, still missing is the ability to parse images from within the content.

Use Images with your Content

Strapi easily saves your images to whichever Provider is configured. In this tutorial, it is Cloudinary. However, not all projects will use Cloudinary and in development, images are often saved to Strapi locally. Therefore, you will need to set an environment variable and instruct Gatsby how to parse the image path.

Setting and using environment variables is a big subject. This Gatsby article does a good job explaining how Gatsby uses them.

In this tutorial, an environment variable is used to prepend http:localhost:1337 to the image path for image uploaded in Development (gatsby develop) as Strapi is saving the images locally.

Path: ./blog/

In the Gatsby project root create a file and call it .env.development. Add the following line:

IMAGE_BASE_URL=http://localhost:1337

This has created a variable called IMAGE_BASE_URL which the Reactmarkdown component will use IF the image path does not have a complete URL.

React-markdown has an option called, transformImageUri. This option makes the image path available for use within the component and so within its value pair, a ternary operator will be used to provide the logic and check if its a complete path or not. If it is not a complete path, the env variable will be used to create one.

NOTE: This simple checks if uri starts with http, if it does then it's a complete path and if it doesn't then it is locally hosted with a relative path and the IMAGE_BASE_URL is prepended.

Note: You can check if this works by going to Plugins > FILES UPLOAD > cog and changing the Provider back from Cloudinary to Local Provider. You will need to add back your images from within your Content Types to test this.

You content is now properly parsed and transforming from Markdown to HTML. The following section is an Optional section that will provide some styling (and instruction) for the index.js and author.js pages and also implement and allow the use of plain HTML within the content.

OPTIONAL: Creating a Basic Blogroll

The index.js page currently displays every article. The issue is that the page displays the entire article. Normally, on this type of index page, a snippet is showed with a Read more link.

To accomplish this functionality various things need to be done:

Add a CSS class through the react-markdown package and component

This CSS class allows for removing the images as well as give a uniform height with CSS for the content in the index type pages.

Add JavaScript to omit any text after 500 characters and add ... to the end of the snippet.

Add a link for the Read more.

Add a global.css stylesheet with a few styles.

These changes are the same for both the index.js page and the author.js template. Edit these files like this:

Add the import statement for each of the other pages you would like to have global CSS Styles for.

OPTIONAL: Adding plain HTML support to the markdown

Your project has index pages that show snippets and provide your users a link to read the full article. The next optional part of this section is to add HTML-in-Markdown support to your markdown.

By default, react-markdown escapes HTML contained with the markdown. This is done when the editing environment is not controlled and unwanted code injections are being guarded against. However, with the Strapi editor this is not a problem and there are various scenarios where supporting HTML-in-Markdown is desirable.

In this tutorial, the use case demonstrated is the ability to add classes to the images within the content. It is expected that your CSS will have a default size for the content images. In this case, using markdown syntax for the images is perfect.

For smaller, larger or floated images, for example, HTML support is needed as markdown does not natively support adding classes within the editing experience.

There are two steps to configure your project to allow HTML-in-Markdown:

Add the react-markdown option that sets the escapeHTML={false} from {true}

Add a few CSS classes for .small and .large CSS classes.

Set the 'escapeHTML' option

React-markdown sets an option called, escapeHTML to true by default. You need to set this to true. Add the escapeHTML={false} option to your <Reactmarkdown /> component. Like this:

Update Git repo for the project to update Netlify

Netlify makes it easy to update the project. Once you push to GitHub, Netlify will automatically rebuild the project.

Path: ./blog/

git add .
git commit -m "added markdown support"
git push

After a few minutes, your Gatsby project hosted on Netlify will have its files updated and you can go to your Strapi installation on Heroku and add an article Content Type which will now use and properly display markdown.

Conclusion

Congrats! You’ve successfully built a super fast and easy-to-maintain blog!

Since the content is managed by Strapi, the authors can write articles through a nice UI and developers only have to rebuild the Gatsby blog in order to update the content.

Where to go next?

Feel free to continue this project to discover both Gatsby and Strapi advantages. Here are some features you can add: list of authors, article's categories, and comment system with the Strapi API or Disqus. You can also create other types of websites (e-commerce shop, corporate website, etc.).

When your project is achieved, you will probably want to deploy it. The static website generated by Gatsby can easily be published on storage providers: Netlify, S3/Cloudfront, GitHub pages, GitLab pages, Heroku, etc. The Strapi API is a headless CMS, so it can be hosted on Heroku or any Linux instance that has Node.js installed.