Setting up (and migrating) a simple blog with Gatsby and Netlify CMS

Gatsby is a site-generator powered by React and GraphQL. It can use multiple sources for data, and outputs static HTML,CSS and React files that can be deployed on multiple static site hosting providers, such as Netlify and GitHub pages.

In fact, this very blog uses Gatsby and is hosted on Netlify.

My goal was to take an old Hugo powered blog and upgrade it to use Gatsby without having to rewrite any of the content. The reason for this was because the Hugo version was incredibly old, and updating to a new version broke a lot. Furthermore, the theme was not updated, and the viable solution was to update it. I decided to use a theme that is provided by the Gatsby theme, so that I can ensure that it will be updated.

The old blog used Netlify CMS to provide a handy web interface to edit and add new content. I am using plain markdown files for each blog post, and Gatsby supports markdown content, so I only had to figure out how to setup the framework and then copy in the previous content. I wanted the new blog to work with the current CMS setup without requiring much tweaking.

Node.js was needed, and so at the time of writing I used the latest stable edition, which was v12 (the specific version was 12.16.3). It is important to note Gatsby’s Node version support:

Gatsby aims to support any version of Node that has a release status of Current, Active, or Maintenance. Once a major version of Node reaches End of Life status Gatsby will stop supporting that version.

The first step that I took was to install the Gatsby CLI. With this tool, I can manage the project by building and testing. The command to install the tool is:

npm install -g gatsby-cli

The blog theme that I chose to use is the starting Gatsby blog theme.

Once the CLI is installed, a new blog can be created with the following command:

gatsby new my-blog

where my-blog is the name of your blog and can be changed. The tool takes care of creating all of the necessary folders and files. Once it is finished, your structure (at the time of writing this) should resemble the diagram below:

│   └───assets
|   │       avatar.png
│   └───posts
│           firstpost.mdx
│           secondpost.mdx
│   └───gatsby-theme-blog
│       └───components
│                bio-content.js
│       └───gatsby-plugin-theme-ui
│                colors.js
│   .prettierrc
│   gatsby-config.js
│   package.json

The content folder holds assets such as images and posts, which is where the markdown files will live. It is important to note that this theme uses the file format mdx which allows for interactive JSX components to be imported and used directly in the file. Regular markdown is written alongside it. The avatar.png can be replaced by any image of your choosing (but it must have the same name). It is the image that appears on the landing page of the site next to the biography content.

The src folder holds the components that are editable. In this case, we can change the content of bio-content.js to contain whatever text we want to appear on the landing page. The colors.js file lets us override the default theme colours.

The gatsby-config.js file is where we configure the site plugins as well as site metadata and other options. Gatsby has a very extensive plugin system, and many common functionalities can be installed from npm and added to the config file.

Installation instructions as well as configuration options for each plugin can be found on their respective website. For most of them, there are no options to configure, but for some you may want to tweak them to get what you desire. Once installed and added, my gatsby-config.js file resembles the content below:

module.exports = {
  plugins: [
      resolve: `gatsby-plugin-nprogress`,
      options: {
        color: `tomato`,
        showSpinner: true,
      resolve: `gatsby-theme-blog`,
      options: {},
      resolve: "gatsby-plugin-manifest",
      options: {
        name: "",
        short_name: "",
        start_url: "/",
        background_color: "#0097a7",
        theme_color: "#26c6da",
        display: "minimal-ui",
        icon: "content/assets/icon.png",
        lang: "en",
        cache_busting_mode: "query",
  // Customize your site metadata:
  siteMetadata: {
    title: ``,
    author: ``,
    url: "",
    siteUrl: "",
    description: ``,

This setup configures the Netlify CMS and any files it requires, a cache to build faster on Netlify’s servers, a progress bar to indicate page load, a sitemap.xml and robots.txt generator, and manifest settings so that the blog can become a Progressive Web App.

And now, we have set up a basic blog with Gatsby! I had the Netlify CMS configured beforehand, since the old blog had used, but I will share the steps below that I took to configure it.

In the project root, add a file config.yml in static/admin/ (create the folder structure if you do not have it already). This configuration file is what Netlify uses to configure the CMS for your site. There are a plethora of options that you can set. I have configured mine to build from the GitHub repo directly, and my settings are shown below:

  name: git-gateway
  branch: master

publish_mode: editorial_workflow
media_folder: "content/images/uploads"

  - name: "blog"
    label: "Posts"
    label_singular: "Post"
    extension: mdx
    format: frontmatter
    folder: "content/posts"
    create: true
    slug: "{{slug}}"
      - { label: "Title", name: "title", widget: "string" }
      - { label: "Body", name: "body", widget: "markdown" }
      - { label: "Date", name: "date", widget: "datetime" }

After this, you would need to go into Netlify and enable the Identity option so that you are able to log in with a Google (or other provider) account. Furthermore, you can configure which GitHub repo it pulls from, and other settings. As mentioned before, Gatsby requires that the Node version is not end-of-life, and so you must add an environmental variable to specify the current Node version. I have specified version 12.16.3, which is currently the newest LTS version.

At this point, I have (almost) migrated my blog from Hugo to Gatsby while keeping the Netlify CMS setup. The last step for me was to transfer the post files to content/posts. Additionally, I would have to rename each md file to mdx. For this, thanks to this Stack Overflow answer, I was able to use the following script to convert all of the files at once:

for file in *.md; do mv "$file" "${file/.md/.mdx}"; done

Thank you for reading my short article on how I updated my post to a different static-site generating framework. Perhaps in a couple of years, there may be yet another upgrade post.