How to create a related post component with gatsby-remark-related-posts plugin
Tags: gatsby, webdev, codenewbie
Published: 2021-06-22 14:39:02

<em><small>This article is originally published on [miyazakimaiko.com](https://miyazakimaiko.com/). Photo by <a href="https://unsplash.com/@girlwithredhat?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Girl with red hat</a> on <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash.</a></small></em>

## Motivation

I recently deployed my personal blog [miyazakimaiko.com](https://miyazakimaiko.com), but I had difficult time dealing with a related post component when I build this website. I found a couple of ways to implement it without a plugin, but I wanted it as simple as possible, preferably complete it on the build time, and didn't mind using a plugin for it. Then I found gatsby-remark-related-posts plugin, which seemed feasible, but I couldn't find solutions to some of the issues I came across when implementing it. So this article is for the people who stuck like me. I'll summarise implementation steps to make it as easy as possible to understand.

## Requirements

**Using allMarkdownRemark for querying .md files**
Unfortunately, it seems like it's not compatible with .mdx files or mdx query. If you find it possible, please let me know in the comment section!
    
**gatsby-remark-related-posts plugin is installed**

To install the plugin, please refer to [this page](https://www.gatsbyjs.com/plugins/gatsby-remark-related-posts/).

**File hierarchy**
 
```js
project
│   gatsby-config.js
│   gatsby-node.js   
│
└───content
│   └───blog 
│       └───article1   
│       │   │   index.md
│       │   │   featured_image.jpg
│       │
│       └───article2
│       │   │   index.md
│       │   │   featured_image.jpg
│       
└───src
│   └───templates 
│       └───article.js
...     ...

```
This folder is used as the example.


## Implementation

### gatsby-config.js

Set directory where you include your markdown files in `posts_dir`, like this:

```js
plugins [
  {
    resolve: "gatsby-remark-related-posts",
    options: {
      posts_dir: `${__dirname}/content/blog`,
      doc_lang: "en",
    },
  },
]
```

### gatsby-node.js

**Query part**
This code below allows the plugin to create relatedFileAbsolutePaths field in the each `MarkdownRemark` node. Details: https://www.gatsbyjs.com/plugins/gatsby-remark-related-posts/

**createPages action part**
Pass the `relatedFileAbsolutePaths` as a variable to the individual page. To do so, we can simply set `relatedFilePaths: post.node.fields.relatedFileAbsolutePaths.slice(0,4)` inside context. You could just pass whole list of related file absolute paths, or specify how many article you want to pass by slicing the list.

```js
exports.createPages = async ({ graphql, actions }) => {
    
  const { createPage } = actions

  const blogPostCollection = await graphql(
    `
      {
        allMarkdownRemark {
          edges {
            node {
              fileAbsolutePath
              fields {
                relatedFileAbsolutePaths
              }
              frontmatter {
                title
                slug
              }
            }
          }
        }
      }
    `
  ).then(result => {
    if (result.errors) {
      throw result.errors
    }

    // Create an individual article page for each article.
    const posts = result.data.allMarkdownRemark.edges

    posts.forEach((post, index) => {
      createPage({
        path: `blog/${post.node.frontmatter.slug}`,
        component: path.resolve(`./src/templates/article.js`),
        context: {
          slug: post.node.frontmatter.slug,
          relatedFilePaths: post.node.fields.relatedFileAbsolutePaths.slice(0,4),
        },
      })
    })

    // Create blog list pages here..

    return null
  })

  await Promise.all([blogPostCollection])
}
```

*Caution with the Query: In my blog, I set `slug` as a part of frontmatter, but most of cases you have `slug` field.*

## templates/article.js

We can simply query related posts when fetching the single article like below. Make sure to mention the argument `$relatedFilePaths: [String]`, which we passed to this page in the gatsby-node.js file.

```js
export const query = graphql`
    query BlogTemplate($slug: String! $relatedFilePaths: [String]) {
        markdownRemark(frontmatter: { slug: { eq: $slug } }) {
            ...
        }
        allMarkdownRemark(filter: {fileAbsolutePath: {in: $relatedFilePaths}}, limit: 4) {
            edges {
              node {
                ...
            }
        }
    }  
```

In the template, you'll be able to access the main article data from `props.data.markdownRemark` and related posts data from `props.data.allMarkdownRemark.edges`.

![related post component is created](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5cpxsccqa6zky5folvkw.jpg)

Hooray! Now I have a related posts component available to the each page 🎉

## Consideration

This plugin accumulates related posts on the build time rather than runtime, so I'd say it's highly efficient. However, I do not have much articles on my blog so I don't yet know tell how it affects the speed of the build time. I'll do more research about it, and update this article when I find any realization in the future.

Thanks for reading. If you have any opinion or question, please leave a comment below!