DevYarns

Beginner's Guide to Blogging with Gatsby: The Blog Post Template

August 08, 2020

This tutorial assumes your blog uses Gatsby and that your Gatsby blog already has a blog post template that displays content from Markdown files.

If you created your site using one of the popular Gatsby starters for blog sites, you should already have a blog post template file.

I created my blog using the Gatsby Starter Blog. The path to the blog post template for the starter I used is src/templates/blog-post.js.

This tutorial will not teach you how to create your own blog post template from scratch. Instead, I will teach you how to read and understand your pre-existing template. I recommend opening up your template next to this post and following along.

For a deep dive into creating a blog-post.js template file from scratch, check out Part Seven of the Gatsby tutorial.

Understanding the Parts of the Blog Post Template

The essential parts of the blog post template are as follows:

  1. Imports
  2. Component
  3. Return Statement
  4. Export
  5. GraphQL Query

Imports

At the top of the file, we import the libraries and files we need. At minimum, we need React to be able to use Gatsby and GraphQL to query our data. We may also need a Layout component to wrap our page.

This is where other imports should go, too, if you need them.

import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
// Other imports here as needed

Component

Next, we should have a React component to render the template. The Gatsby Starter Blog uses a functional component called BlogPostTemplate.

const BlogPostTemplate = ({ data, pageContext, location }) => {
  // function content here
}

Return Statement

Inside our component, we need a return statement that tells Gatsby how to display our blog posts. This is where we create the structure of our blog post. We inject the content of our blog post here, as well.

Below is a simplified version of what you might want to return. Recall that location and data were passed into your component as props.

return (
   <Layout location={location} title={data.site.siteMetadata.title}>
    <article>
        <header><!--- post header here ---></header>
        <!--- post content injected below: --->
        <section dangerouslySetInnerHTML={{ __html: data.markdownRemark.html }} />
        <footer><!--- post footer here ---></footer>
    </article>
   </Layout>
)

Export

After our component, we need to export it so Gatsby can use it.

export default BlogPostTemplate

GraphQL Query

Finally, we need a GraphQL query that asks our file system for some data about our site and our posts. This is how we get the blog post data that we inject in the return statement.

export const pageQuery = graphql`
  query BlogPostBySlug($slug: String!) {
    site {
      siteMetadata {
        title
        siteUrl
      }
    }
    markdownRemark(fields: { slug: { eq: $slug } }) {
      id
      html
      frontmatter {
        title
        path
        date(formatString: "MMMM DD, YYYY")
      }
    }
  }
`

The site section of the query asks for the title and URL of our site from the site metadata.

The markdownRemark section gets info on the single post to display. The fields inside the frontmatter section come from the info you can add to the head of each post’s Markdown file. For example, the following is from the top of the Markdown file I wrote for this post:

---
path: gatsby-blog-post-template
date: 2020-08-07
title: "Beginner's Guide to Blogging with Gatsby: The Blog Post Template"
---

If you add additional fields to this part of your Markdown files, you can query for those additional fields by adding their names to the query.

For example, you could add ”description: Post description here” to the head of your blog post. Then, you could modify the query to include a description field as follows (see the highlighted line):

export const pageQuery = graphql`
  query BlogPostBySlug($slug: String!) {
    site {
      siteMetadata {
        title
        siteUrl
      }
    }
    markdownRemark(fields: { slug: { eq: $slug } }) {
      id
      html
      frontmatter {
        title
        path
        date(formatString: "MMMM DD, YYYY")
        description      }
    }
  }
`

For more on using GraphQL with Gatsby, check out the official Gatsby documentation on querying your data with GraphQL.

All Together

Putting it all together, here is a simplified version of what your blog post template might look like:

// Imports
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
// Other imports here as needed

// Create the component
const BlogPostTemplate = ({ data, pageContext, location }) => {
  const post = data.markdownRemark
  const siteTitle = data.site.siteMetadata.title

  // Return statement
  return (
    <Layout location={location} title={siteTitle}>
      <article>
        <header><!--- post header here ---></header>
        // post content injected below:
        <section dangerouslySetInnerHTML={{ __html: post.html }} />
        <footer><!--- post footer here ---></footer>
      </article>
    </Layout>
  )
}

// Export the component
export default BlogPostTemplate

// GraphQL query to get site and post data
export const pageQuery = graphql`
  query BlogPostBySlug($slug: String!) {
    site {
      siteMetadata {
        title
        siteUrl
      }
    }
    markdownRemark(fields: { slug: { eq: $slug } }) {
      id
      html
      frontmatter {
        title
        path
        date(formatString: "MMMM DD, YYYY")
      }
    }
  }
`

What’s Next?

Now that you have a basic understanding of the parts of a Gatsby blog post template, you can try modifying and extending it!

I recommend starting with my post on extending the blog post template to add an auto-populated tweet link: How to Add Click to Tweet Links to Your Gatsby Blog.


Rachel Leggett, is an Ann Arbor-based front-end web developer, accessibility specialist, and knitwear designer. She spins some yarns about web development, web accessibility, and other tech topics in the DevYarns blog.

© Rachel Leggett, Built with Gatsby