FSociety

Using GraphQL queries to separate pages and blog posts in Gatsby

June 05, 2019

When starting this blog with Gatsby one of my main problems was to filter out my “about me” or any other pages from the list of blog posts. If you don’t use Markdown files for your static pages, this task is as simple as creating separate React components for each page. However, if like me, you wanted to use Markdown for your static pages you would have the problem of seeing your pages in the list of blog posts!

In the beginning, I used my JavaScript skill to filter out the results but I wasn’t happy with that. Recently I learned a better approach using GraphQL and that’s what I’m describing in this post.

Using frontmatter

First, we need a mechanism to tag markdown files that we are using for our pages. Frontmatter (the fields specified on top of your markdown files) is a good place to tag some posts as pages. This is how I do it:

---
title: My page title
date: 05/06/2019
page: true
---

As you can see, in this markdown file I tagged the page property (could be anything else) as true. Now in my index.js which I am listing all my blog posts, I have the possibility to filter out the markdown files that their page property is false.

Excluding pages from blog posts

At this moment that I have my page field ready in the frontmatter, removing the pages from blog posts results is as simple as one extra line to your GraphQL query:

// index.js (or wherever you are showing the list of your blog posts)
export const pageQuery = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
    allMarkdownRemark(
      sort: { fields: [frontmatter___date], order: DESC }
      filter: { frontmatter: { page: {ne: true}}}    ) {
      edges {
        node {
          excerpt
          fields {
            slug
          }
          frontmatter {
            date(formatString: "MMMM DD, YYYY")
            title
          }
        }
      }
    }
  }
`

Pay attention that I’m using the filter argument on allMarkdownRemark query. ne is a reserved keyword that would stand for “Not Equal”. If you are not sure about the options available for filtering, you can always use the graqhiQL (accessible at localhost:8000/__graphql) to check them out:

graphiql filter fields

Querying the correct page

Now we need to make a new component in our /pages directory and query the page correctly. However, for every page, we probably want to make a new component and there is no way to figure out which page, belongs to which component from the frontmatter.

In order to simply serve a specific page in a component according to the name of the markdown file, we can simply use the slug field which is available in our GraphQL data:

export const pageQuery = graphql`
query {
  site {
    siteMetadata {
      title
      author
    }
  }
  markdownRemark(
    fields: { slug: { eq: "/about-me/" }}  ) {
    excerpt
    html
    frontmatter {
      title
      date
    }
  }
}
`

With this query, you can access to all the data of your post in this.props.data.markdownRemark on the very same component you are executing this query with!

Conclusion

This solution is appropriate for the use case of having limited pages with different designs. If you need to have a dynamic number of pages, you don’t want to create new components for each of them and you need to make some changes in your createPage function of you gatsby-node.js file to render Page components differently.


Pooria Atarzadeh

Personal blog by Pooria Atarzadeh
Unattended curiosity on web, graphql, blockchain and more

About Me