Posted by : at

Category : react   gatsby


Part 6- Adding Markdown Blog to Gatsby Site

This is a part of a series - How to Create a Gatsby Blog from Scratch

In this part, we gonna be adding markdown support to our gatsby site, to create a blog using markdown files (that acts as posts).

Lets get started !

Gatsby can use Markdown files to create pages in your site.

  1. Read files into Gatsby from the filesystem:

we gonna need to install plugins to support Gatsby to read files from the filesystem :

yarn add gatsby-source-filesystem

Now we need to add the plugin to our gatsby-config.js

 plugins: [
   {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `pages`
        path: `${__dirname}/src/pages`,
      }
    }
]

In this we are trying to set the file system path, blog folder will contain all our markdown files, which gatsby will use to read from the filesystem.

  1. Transform Markdown to HTML and frontmatter to data

We need to use a plugin gatsby-transformer-remark to recognize files which are Markdown and read their content.The plugin will convert the frontmatter metadata part of our Markdown files as frontmatter and the content part as HTML

Install transformer plugin:

yarn add gatsby-transformer-remark

Now we need to add the plugin to our gatsby-config.js

plugins: [
 {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `pages`
        path: `${__dirname}/src/pages`,
      }
    },
     {
      resolve: `gatsby-transformer-remark`,
      options: {
         plugins: []
      }
    }
]

So Gatsby gonna look to the pages folder for our markdown files :

Lets create a post inside pages/posts/hello-world.md

---
path: "/hello-world"
date: 2017-07-12T17:12:33.962Z
title: "Happy New Year - 2020 !"
---

Wishing Everyone a very Happy New Year 2020 :D

The frontmatter part consists of path, date and title of the post which is used by graphql for the data

We need to configure a way to dynamically create pages from our markdown posts. create a new file gatsby-node.js, to tell gatsby about the slugs and the pages it needs to create out of the markdown posts:


const path = require(`path`);
const { createFilePath } = require(`gatsby-source-filesystem`)

// function that gets called whenever a new node is created or updated
exports.onCreateNode = ({ node , getNode, actions }) => {
    const { createNodeField } = actions
    if (node.internal.type === `MarkdownRemark`){
        const slug = createFilePath({ node, getNode, basePath: `posts`})
     //   console.log(createFilePath({node, getNode, basePath: `posts`}))

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

// function to create pages
exports.createPages = async ({ graphql , actions }) => {
    // graphql function call returns a promise

    const { createPage } = actions

    const result = await graphql(`
      query{
        allMarkdownRemark {
          edges {
            node {
              fields {
                slug
              }
            }
          }
        }
      }
    `)
    console.log(JSON.stringify(result, null, 4))
    result.data.allMarkdownRemark.edges.forEach(({node}) => {
        createPage({
            path: node.fields.slug,
            component: path.resolve(`./src/templates/blog-post.js`),
            context: {
                // Data passed to the context is available
                // in page queries as Graphql variables
                slug: node.fields.slug,
            },
        })
    })
}

Lets now list our blog posts. We are going to create a new page blog.js

import { graphql, Link } from "gatsby"
import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"

export const query = graphql`
         query {
           allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
             totalCount
             edges {
               node {
                 frontmatter {
                   date
                   title
                 }
                 fields {
                     slug
                 }
                 html
                 excerpt
               }
             }
           }
         }
`

const Blog = ({ data }) => (
  <Layout>
    <SEO title="Blog"></SEO>
    <h1> Blog</h1>
    <h4> Showing {data.allMarkdownRemark.totalCount} Posts </h4>

    {data.allMarkdownRemark.edges.map(({ node }) => (
      <div key={node.id}>
        <Link to={node.fields.slug}>
          <h3>{node.frontmatter.title}</h3>

          <p>Posted at: {node.frontmatter.date}</p>
          <p> {node.excerpt}</p>
        </Link>
      </div>
    ))}
  </Layout>
)

export default Blog

To make the individual blog posts we will be using a template (blog-post.js)

import { graphql } from "gatsby"
import React from "react"
import Layout from "../components/layout"

export const query = graphql`
         query($slug: String!) {
           markdownRemark(fields: { slug: { eq: $slug } }) {
             html
             frontmatter {
               title
             }
           }
         }
       `

export default ({ data }) => {
  const post = data.markdownRemark
  return (
    <Layout>
      <div>
        <h1>{post.frontmatter.title}</h1>
        <div dangerouslySetInnerHTML= >
      </div>
    </Layout>
  )
}

That’s all, you will be having a working blog similar to something like this :

Demo