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:
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.