Author: Richard Haines

Posted: 31 Jul 2020

take me there

  • Frontmatter
  • The blog index

So let's say you have your Gatsby blog all setup using MDX for your blog posts. Perhaps you have written a post that you want to pin to the top of your list of posts in your blog index, this post is awesome and you want people to see it when they first arrive to your blog.

There is no magic here, just adding a new value to our posts frontmatter and filtering on that post. Let's dive into some code examples shall we! 😀

Frontmatter

In the your posts frontmatter add a new field, pin. This will be a boolean value.

1---
2title: Pinned blog post
3date: 2020-07-31
4published: false
5category: Whatever
6author: Richard Haines
7keywords: [mdx, blog, pinned post, gatsby]
8pin: true
9---

The blog index

In the blog index you'll most likely have a query so that you can fetch your posts and pass them to the MDXRenderer. Add the new field value to the frontmatter.

1export const query = graphql`
2 query BlogIndexQuery {
3 allMdx(sort: { fields: [frontmatter___date], order: DESC }, filter: { frontmatter: { published: { eq: true } } }) {
4 nodes {
5 id
6 excerpt(pruneLength: 200)
7 frontmatter {
8 title
9 date(formatString: "DD MMM YYYY")
10 category
11 author
12 pin
13 }
14 fields {
15 slug
16 }
17 }
18 }
19 }
20`;

Create a new variable called pinned and filter the passed in mdx nodes by the pin frontmatter field. Then create a nice ternary to check if any posts are in fact pinned or not.

1const pinned = data.allMdx.nodes.filter(post => post.frontmatter.pin === true);
2 const allPosts = pinned.length
3 ? [pinned[0], ...data.allMdx.nodes.filter(post => !post.frontmatter.pin)]
4 : data.allMdx.nodes;

The allPosts variable will be passed and used to render the posts in nice cards or however you choose to display them. We can now check the frontmatter and see if a post is pinned or not. I like to use Theme-ui to style my components but this same code can be used with CSS. In the container card for your blog post add a before pseudo element that only shows if the post is pinned.

1// ...the component
2 <div
3 sx={{
4 // ...card styles
5 ":before": frontmatter.pin
6 ? {
7 content: "'Pinned'",
8 width: "6em",
9 backgroundColor: "accent",
10 color: "background",
11 textTransform: "uppercase",
12 fontFamily: "heading",
13 fontWeight: "bold",
14 letterSpacing: "body",
15 display: "flex",
16 justifyContent: "center",
17 alignItems: "center",
18 borderRadius: "5px"
19 }
20 : null
21 }}
22 className="card"
23 >
24 // show the title and excerpt, maybe a nice picture from your post
25 </div>

And thats it, viola! ✌️

Edit on GitHub.Previous: use-cloudinary - useUpload hookNext: React Emoji Component