Building a markdown-based blog with GatsbyJS

Before moving to GatsbyJS I was using Jekyll as the platform for my personal website. It included the blog, and Jekyll is a great tool for that. The generated static site was fast to load, with many responsive themes, and it was a pleasure to write new content as the defacto way is using markdown.

However, Jekyll is written in Ruby, using RubyGems as the package manager, and I don't use Ruby in a daily basis. The only usage is from time to time to instal Cocoa Pods dependencies when running an iPhone simulator. Ruby is great, I used to build Ruby on Rails sites and some scripting. But I didn't do much Ruby development in the last few years, and maintaining a site in Ruby has become a bit time-consuming, especially dealing with deprecations, build issues, etc.

Since I have used, and still do, ReactJS a lot more, it feels a lot more practical to manage NPM dependencies. NPM is the Node.js package manager. And all the praises over the net around GatsbyJS, with a few previous small projects before, I gave it a try as it has the benefit to give some introduction to the GraphQL protocol.

After researching that all requirements were covered, building basic pages was simple enough, and the result build was impressive: very fast, optimized images, and when available, the data is provided at build time (not at runtime) to views, which improves performance.

It has TypeScript support which was enough to convince me. Having the option to write unit tests in TS if necessary, and especially configure ESLint rules along with Prettier, I decided to setup my personal website with this stack reusing previous setup and it was completed in a couple of days.

Adding a similar support as Jekyll to writing in Markdown took a bit more time, but it was fairly simple too. The approach for this is edit two files:

  • gatsby-config.js: This handles which files are supported, and GatsbyJS plugins
  • gatsby-node.js: For the setup of the build and data usage configuration
  • gatsby-browser.js: In order to import the PrismJS theme

For the important plugins (more were used) added in gatsby-config.js:

  • gatsby-transformer-json: Adds support to query local JSON files via GraphQL
  • gatsby-remark-external-links: Allows to open markdown links in new tab
  • gatsby-source-filesystem: Can accept paths to parse multiple file types: JSON, Markdown, Images, etc.
  • gatsby-transformer-remark: Parses Markdown files and allows to create pages with that
  • gatsby-remark-prismjs: Adds syntax highlighting to code-blocks from remark

Once the data was available, the next step is top use it to create new pages and manipulate the data a bit. Two methods of the GatsbyJS Node API were used in gatsby-node.js:

  • createPages: Here the data is read using GraphQL and used to create pages

A summary:

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions
  const postTemplate =
    path.resolve("src/templates/post.js")

  const result = await graphql(
    `
      {
        allMarkdownRemark {
          edges {
            node {
              frontmatter {
                description
                layout
                title
              }
              fields {
                slug
                path
              }
              html
            }
          }
        }
      }
    `
  )

  const markdownItems =
    result.data.allMarkdownRemark.edges

  // some error handling ...

  markdownItems.forEach(({ node }) => {
    if (node.frontmatter.layout === "post") {
      createPage({
        component: postTemplate,
        context: {
          description: node.frontmatter.description,
          html: node.html,
          title: node.frontmatter.title,
        },
        path: node.fields.path,
      })
    }
  })
})

Also the onCreateNode method was used:

onCreateNode = ({ node, actions }) => {
  const { createNodeField } = actions

  if (
    node.internal.type === "MarkdownRemark" &&
    node.frontmatter.layout === "post"
  ) {
    const slugs = node.fileAbsolutePath.split("/")
    const slug = slugs[slugs.length - 1]
      .replace(".md", "")
      .replace(...) // some parsing of the names
    const postPath = `/blog/${slug}`

    createNodeField({
      name: "slug",
      node,
      value: slug,
    })

    createNodeField({
      name: "path",
      node,
      value: postPath,
    })
  }
}

The createNodeField helper method allows to add arbitrary properties to GraphQL nodes.

Learning some GraphQL basics and using the interactive GraphQL web IDE was very interesting.

After this simple setup, I was able to have the same experience as with Jekyll, with the same result, but avoiding the Ruby issues (due to my lack of usage) and allowing a better maintenance and easier addition of features. If you have experience with the JS stack (React) and don't want to spend much time maintaining your personal website, GatsbyJS is a great choice.

Back to the posts list
Loading ...