When I started my 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.
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.
Top comments (1)
Wow, Thanks for the article. I am new to Graphql and
filter: { frontmatter: { page: {ne: true}}}
this line saved me.