Surfacing Tags from Contentful
Thursday, April 29, 2021
Intro
After setting up the contentful gatsby blog starter and running the setup configuration in the readme you'll be hitting the ground running with a fully functional vehicle to start delivering your blog content. It comes with some starter data to help you get a lay of the land and understand the internals if you want to go deeper. However, looking a little closer you can see that the blog posts have tags, but our output system doesn't show the tags at all. Let's dive in and get that working.
GraphQL
What makes gatsby so powerful is the usage of GraphQL to be able to source your content, and build it based on templates in your system. I've only dipped my toe slightly here, so this could be quite an over simplification, but that's what I have uncovered so far. Locally you can see the schema that you are working with by looking at http://localhost:8000/__graphql
.
Assuming you are starting with the same starter kit I mentioned above, with some previous experience with GraphQL you could dig in and see that our tags are exposed in the graph.
query MyQuery {
contentfulBlogPost {
id
author {
name
}
tags
}
}
{
"data": {
"contentfulBlogPost": {
"id": "...",
"author": {
"name": "David Larrabee"
},
"tags": [
"gatbsy",
"learning",
"tagging"
]
}
},
"extensions": {}
}
So we just need to surface when we generate our blog content with our templates - lucky us.
Updating the Template
Templates are stored in src/templates
, we've only got the single template today that we want to edit which is blog-post.js
. Templates follow a pretty common pattern, there is a query at the bottom of the file to surface our data, and the actual content is exposed above working with your react components.
So with a couple quick changes, we can surface our blog tags. We just have to update these two areas.
Query
Our blog post template query looks like this today
export const pageQuery = graphql`
query BlogPostBySlug($slug: String!) {
contentfulBlogPost(slug: { eq: $slug }) {
title
publishDate(formatString: "MMMM Do, YYYY")
heroImage {
fluid(maxWidth: 1180, background: "rgb:000000") {
...GatsbyContentfulFluid_tracedSVG
}
}
body {
childMarkdownRemark {
html
}
}
}
}
the items wrapped within contentfulBlogPost
are the various fields avaiable that we are using in our blog today. Things like title
and body
, so we just need to add tags
into the mix there. I've placed it directly under title
in my page query.
Content
Now that we have the query updated to include our tag data, we just need to surface it in the UI our blog post is built with. That's surface above in the same file, looks something like this
<Layout location={this.props.location}>
<div style={{ background: '#fff' }}>
<Helmet title={`${post.title} | ${siteTitle}`} />
<div className={heroStyles.hero}>
<Img
className={heroStyles.heroImage}
alt={post.title}
fluid={post.heroImage.fluid}
/>
</div>
<div className="wrapper">
<h1 className="section-headline">{post.title}</h1>
<p
style={{
display: 'block',
}}
>
{post.publishDate}
</p>
<div
dangerouslySetInnerHTML={{
__html: post.body.childMarkdownRemark.html,
}}
/>
</div>
</div>
</Layout>
Similarly here, you can do whatever you'd like as far as styling the tags etc - but our quickest thing is to just throw it into the content and see it working. Looking in the GraphQL query we can see that tags is an array of values, so why don't we just join them together and show them around the publish date for simplicity
{post.publishDate}<br />
Tags: {post.tags.join(', ')}
There you have it - the tags from your contentful post, showing on the articles for your readers to see.
What's next?
Well similar to what I did in some of my original posts, we probably want to surface a page which shows these posts based on the tags - etc. Let's pull that together another post.