New Launch

Take a deep dive into the fastest Gatsby, yet: Gatsby 5!

ContactSign Up for Free

Content Querying with Gatsby + Contentful

Paul Scanlon
November 22nd, 2021

If you’re looking to get started with Gatsby and Contentful have a peek at my Quick Start Guide

If you’re already a little familiar with Gatsby and Contentful then great, read on! 

In this post I’ll be explaining how you can make use of Gatsby’s useStaticQuery hook to query different kinds of data to use around your site. 

If you’d prefer to jump ahead you can find this demo site on the links below:

Demo: https://contentfulcontentquerying.gatsbyjs.io/

Repo: https://github.com/PaulieScanlon/contentful-content-querying

Before you get going I’d like to cover off some basics. ☝️

As you may already know there are two main types of GraphQL query that can be used with Gatsby, they are as follows:

  1. Page Query

This relates to data that is used by a page or a collection of pages, typically it requires a unique id so Gatsby can determine what data to return to each page.

It can look a little something like this, but more importantly it can’t be “shared” or reused around your site. 

  1. useStaticQuery

This method takes advantage of React’s hooks pattern and provides you with a way to query any kind of data. It can look a little something like this and can be “shared” or reused around your site.

Typically speaking you probably wouldn’t use useStaticQuery to query page content data, but you might, for example, use something like the above which would return a list of the Blog post titles and urls. 

useStaticQuery can be used in a number of ways and in the following examples I’ll show you how to query a list of page links which can be used to create site navigation, and I’ll also explain how to query a list of blog posts links and by using some additional GraphQL functionality you’ll be able to query all the blog posts and the latest blog posts. 

Contentful Pages

To help in the creation of navigation you can add some additional fields to your Contentful Page Content Model. This will allow you to filter the data based on some conditions.  

Here’s the Content Model for my Contentful Page:

Contentful Page Content Page Model

…and here’s the navigation field

Navigation Field Settings

navigation is of type Short Text and by using Contentful’s config options you can add a few extra rules to this field.

Navigation Field Validation

You can set the field to be a Required field as well as only allowing specified values. In my demo these are “top-navigation” and “bottom-navigation”.

Navigation Field Default Value

You can also define a “Default value” for the field. In my demo it’s set to “top-navigation”.

Navigation Field Appearance

And lastly the field’s “Appearance” can be set to “Dropdown”.

Navigation Field Home Usage

Here’s how that field appears for the Home page in my demo. The field is set as the default value of “top-navigation”.

Navigation Field Cookies usage

In the Cookies page however you can see this field is set to “bottom-navigation”.

If you have a look at the demo site again: https://contentfulcontentquerying.gatsbyjs.io/, you’ll see that the Home Page link is at the top of the page in the <header/> and the Cookies link is at the bottom of the page in the <footer />.

Creating hooks

To query this data and to help separate the links required in the “top-navigation” and the “bottom-navigation” You can create your own “hook” which contains Gatsby’s useStaticQuery and then apply a GraphQL filter to test if the navigation field is equal to “top-navigation” or “bottom-navigation”.

To ensure the Home page link, which is “/” appears at position 0 in the list you can sort by the field’s url.

You can see this hook in the src code here: src/hooks/use-top-navigation.js.

For reference you can see the hook for the bottom navigation below which filters on the value “bottom-navigation” src/hooks/use-bottom-navigation.js.

Using hooks

Since these hooks relate to navigation elements and navigation is typically required to persist across all pages you could add them to Gatsby’s wrapRootElement.

In my demo i’ve created a component called <RootElement /> which i use in both gatsby-browser.js and gatsby-ssr.js

You can read more about Gatsby’s API’s in the docs:

Import the hook as you normally would and by using Array.prototype.map() you can iterate over the returned values to create a list of links in both the <header /> and the <footer />.

You can also see how I use these hooks in the src code here: src/componets/root-element.js.

You could also reuse these hooks to create a list of page links for a 404 page for example.

Page Templates

In the demo I’ve used Gatsby’s File System Route API to create a page for each Contentful page… but, and I’m paraphrasing George Orwell here: All pages are equal, but some pages are more equal than others. And just like the pigs some pages may not be the same as others. 🐷

The Home page and the Blog page in the demo site do a little more than just return the data passed from Contentful, they also return a list of blog posts links.

In order to differentiate “/” and “/blog” from the other pages you can add a new field to Contentful’s Page Content Model. In my demo I’ve called this field template.

Template Field Settings

template is of type Short Text and by using Contentful’s config options you can add a few extra rules to this field.

Template Field Validation

You can set the field to be a Required field as well as only allowing specified values.  In my demo these are “home”, “blog” and “default”.

Template Field Apperance

And lastly the field’s “Appearance” is set to “Dropdown”.

Template Field Blog Usage

Here’s how that field appears for the Blog page in my demo. The field is set to the value of “blog”.

Conditional Pages

Now that pages have a field that makes them different from one another it’s possible to switch the type of template to use when Gatsby builds the page.

You can see this file in the src code here: src/pages/{contentfulPage.url}.js.

Template

Here’s the template I use for the Blog page. There’s a prop named contentfulPage which is all the data returned by Contentful but you can also import a hook that returns a list of all the blog post links.

You can see the src code for this template here: src/templates/blog-template.js

And the src for the hook can be found here: src/hooks/use-all-blog-posts.js

For the Home page I use a similar technique and use GraphQL to limit the amount of Blog post links returned.

Here’s what that query looks like:

You can see the src code for this template here: src/templates/home-template.js

And the src for the hook can be found here: src/hooks/use-latest-blog-posts.js

And that just about wraps things up. useStaticQuery is really handy for querying all kinds of data and by abstracting these away into their own hooks means they’re really reusable, they are different to page queries though and I know it can be a little confusing deciding when to use them… my rule of thumb if you like is: if it’s not a page use useStaticQuery.

 

I hope you’ve found this helpful and if you have any questions feel free to come find me on Twitter: @PaulieScanlon

Ttfn

Paul 🕺

Share on TwitterShare on LinkedInShare on FacebookShare via Email

After all is said and done, structure + order = fun! Senior Software Engineer (Developer Relations) for Gatsby

Follow Paul Scanlon on Twitter

Tagged with CMS, contentful, headless-cmsView all Tags

Talk to our team of Gatsby Experts to supercharge your website performance.

Contact Gatsby Now
© 2022 Gatsby, Inc.