Categories
Gatsby.js

Gatsby.js — Render One or More Markdown Files

Spread the love

Gatsby is a static web site framework that’s based on React.

We can use it to create static websites from external data sources and more.

In this article, we’ll look at how to create a site with Gatsby.

Adding Markdown Pages

We can add pages from Markdown by adding the gatsby-transformer-remark and gatsby-source-filesystem plugins.

To do this, we write:

gatsby-config.js

module.exports = {
  plugins: [
    `gatsby-transformer-remark`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `content`,
        path: `${__dirname}/src/content`,
      },
    },
  ],
}

gatsby-node.js

exports.createPages = async ({ actions, graphql, reporter }) => {
  const { createPage } = actions
  const blogPostTemplate = require.resolve(`./src/templates/post.js`)
  const result = await graphql(`
    {
      allMarkdownRemark(
        sort: { order: DESC, fields: [frontmatter___date] }
        limit: 1000
      ) {
        edges {
          node {
            frontmatter {
              slug
            }
          }
        }
      }
    }
  `)

  if (result.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`)
    return
  }
  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    createPage({
      path: node.frontmatter.slug,
      component: blogPostTemplate,
      context: {
        slug: node.frontmatter.slug,
      },
    })
  })
}

src/templates/post.js

import React from "react" { graphql } from "gatsby"
export default function Template({
  data,
}) {
  const { markdownRemark } = data
  const { frontmatter, html } = markdownRemark
  return (
    <div className="blog-post-container">
      <div className="blog-post">
        <h1>{frontmatter.title}</h1>
        <h2>{frontmatter.date}</h2>
        <div
          className="blog-post-content"
          dangerouslySetInnerHTML={{ __html: html }}
        />
      </div>
    </div>
  )
}
export const pageQuery = graphql`
  query($slug: String!) {
    markdownRemark(frontmatter: { slug: { eq: $slug } }) {
      html
      frontmatter {
        date(formatString: "MMMM DD, YYYY")
        slug
        title
      }
    }
  }
`

src/content/post.md

---
title: My First Post
date: 2019-07-10
slug: /my-first-post
---
This is my first Gatsby post written in Markdown!

We add the gatsby-source-filesystem plugin to read the Markdown files from the src/content folder.

And we add the gatsby-transformer-remark plugin to transform the Markdown files to HTML.

Then in gatsby-node.js , we get the Markdown content with the allMarkdownRemark query.

We sort the entries by date with the sort values.

And we limit the number of entries to 1000.

And we specify that we return the slug in the result.

Then we call forEach to call the createPage function to create the pages.

The path is the URL path to access the page.

component has the template file path.

And context has the data that we want to display from the result entry.

In post.js , we have the query to get a single entry.

We get the entry with give slug with the markdownRemark query.

Then we get the html field to get the content.

frontmatter has the metadata for the page.

And we get that from the data prop’s markdownRemark property.

Finally, we render that in the JSX of Template .

Now we should see the post.md content displayed.

Add a List of Markdown Blog Posts

We can also add a page withn multiple posts.

To do this, we write:

src/page/index.js

import React from "react"
import { graphql } from "gatsby"
import { Link } from "gatsby"

const PostLink = ({ post }) => (
  <div>
    <Link to={post.frontmatter.slug}>
      {post.frontmatter.title} ({post.frontmatter.date})
    </Link>
  </div>
)

const IndexPage = ({
  data: {
    allMarkdownRemark: { edges },
  },
}) => {
  const Posts = edges
    .filter(edge => !!edge.node.frontmatter.date)
    .map(edge => <PostLink key={edge.node.id} post={edge.node} />)
  return <div>{Posts}</div>
}

export default IndexPage

export const pageQuery = graphql`
  query {
    allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
      edges {
        node {
          id
          excerpt(pruneLength: 250)
          frontmatter {
            date(formatString: "MMMM DD, YYYY")
            slug
            title
          }
        }
      }
    }
  }
`

We create the PostLink component to display a link for the post.

IndexPage has the posts.

We get the posts data from the data prop’s allMarkdownRemark.edges property.

And we map the entries to the PostLink component to render each entry with the PostLink component.

The pageQuery gets us the data for the data prop.

Conclusion

We can render one or more Markdown files in our Gatsby project.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *