Creating a Pinned Articles Component in Gatsby

First Published: May 28, 2020
If you're looking to learn Gatsby from scratch, I have a 90+ video course called Up and Running with Gatsby. Check it out!

I wanted an easy way to pin articles to the front page of my website. It turns out Gatsby and GraphiQL make this process much easier than you'd think!

First, I added a new pinned field to the frontmatter of the articles I wanted to put on the front page and set it equal to true. Frontmatter fields are great for splicing, dicing, and sorting your content however you'd like.

I then fired up Gatsby's built-in GraphiQL tool and built the following query:

query {
allMdx(
sort: { fields: [frontmatter___date], order: DESC }
limit: 10
filter: {
frontmatter: { published: { ne: false }, pinned: { eq: true } }
fileAbsolutePath: { regex: "//content/writing//" }
}
) {
edges {
node {
id
fields {
title
slug
}
}
}
}
}

This query finds the 10 most recent pinned articles and sorts them by date descending.

What's cool about using a filter of pinned: { eq: true } is that I don't have to go back and add this field to every single article. If I were to change the filter to ne: false like the filter for published, it would include articles that didn't include that field at all. This is because the filter will treat that null reference as a "truthy" value. I'm using the exact same principle in reverse with the published field: I can explicitly set it to false on articles I don't want published, but I don't have to remember to go back and flip that value to true to get them to show up.

I then created a PinnedArticles component and used my query with the useStaticQuery hook that Gatsby provides. Here's the finished component:

// src/components/PinnedArticles.js
const PinnedArticles = () => {
const data = useStaticQuery(graphql`
query {
allMdx(
sort: { fields: [frontmatter___date], order: DESC }
limit: 10
filter: {
frontmatter: { published: { ne: false }, pinned: { eq: true } }
fileAbsolutePath: { regex: "//content/writing//" }
}
) {
edges {
node {
id
fields {
title
slug
}
}
}
}
}
`)
return (
<ul>
{data.allMdx.edges.map((edge) => (
<li key={edge.node.id}>
<Link to={`/${edge.node.fields.slug}`}>{edge.node.fields.title}</Link>
</li>
))}
</ul>
)
}
export default PinnedArticles

All that was left was to replace my hardcoded list of articles in index.mdx with my new <PinnedArticles /> component:

<!-- pages/index.mdx -->
## Some Favorites
These are what I'd considered my "foundational articles." They reflect some of the major lessons I've learned so far on my journey. If you're just getting to know me, start with these:
<PinnedArticles />

And that's it! Now any time I want to pin a new article to the front page, I just set that frontmatter field and I'm on my way.

Practical, actionable ways to improve each week.

Join over 1554 other devs and dev advocates on the Developer Microskills newsletter. Each week, I send out a practical, actionable way to grow in your career. No BS, no hand-waving, but with some fun thrown in for good measure. Sign up and I'll send you the Tiny Experiments framework and worksheet. It's a simple process to help you finish what you start.

Sam Julien © 2015 - Present