Adding the navigation

Prismic no longer recommends the gatsby-source-prismic-graphql plugin

With recent changes to Gatsby, Prismic no longer recommends the gatsby-source-prismic-graphql plugin that this documentation uses. Read more about the future of Prismic and Gatsby. We highly recommend using the gatsby-source-prismic instead. The documentation for this plugin can be found in the plugin's github README.

We will leave this documentation here for now, but will change it in the future when we determine the best approach for Prismic & Gatsby.

Welcome to the 5th article in the Gatsby/Prismic Getting started tutorial series. We'll be walking through the steps required to convert the top navigation from being hardcoded in your Gatsby app to being dynamically created and filled with content from Prismic.

Before reading

If you haven't already gone through the first four articles in this series, we recommend you start with the first article and work your way to this one. After that, this article will make much more sense.

Model the Navigation bar in Prismic

If you don't already have your website running, then open a terminal at the root of your project and run the npm start command to build and launch the site. Looking at the top navigation, you can see that the model will be pretty simple.

We don't know how many links we might need in the future, so we'll need to use a Group field to handle our links. Inside the Group field, we'll need a Link field for the link location and a Rich Text field for the display label.

This model has already been put into place in your Prismic repository, so let's take a look at it now. Go to your Prismic repo, click on the Custom Types button in the left hand navigation, then select your Navigation type. Here you can see how the model was configured in Prismic.

The navigation content model in Prismic

Now let's explore how this looks for content authors. Make sure not to change anything and go back. Then click on the "Content" button on the left to go to your current Prismic content. From here, click on your Navigation document. Here we can see what it looks like with our live content.

The navigation content in Prismic

You can click on the "Add a new element in top_navigation" button to see how easy it is to add a new Link to the nav bar. Now that we have a feel for how this is modeled, let's add this to our Gatsby project.

Query the Navigation document

If you don't already have your project running, use the npm start command in your terminal to launch your project then head to the GraphiQL Explorer: http://localhost:8000/___graphql.

Here is what it will look like, input this query in the left-hand panel of your GraphiQL Explorer:

Copy
{
  prismic {
    allNavigations {
      edges {
        node {
          top_navigation {
            link {
              ...on PRISMIC_Homepage {
                _meta {
                  type
                }
              }
              ...on PRISMIC_Page {
                _meta {
                  type
                  uid
                }
              }
            }
            link_label
          }
        }
      }
    }
  }
}

You can run the query by pressing the "play" button at the top, which should then show you the results of the query on the right.

The working GraphQL query

So we know that the query is working. If you're curious about how this query was constructed check out our documentation for how to retrieve the content fields:

Now that we have our query, let's add it to our Header component.

Update the Header component

Open your project files and navigate to src/components/Header.js. Replace the code there with the following.

Copy
import React from 'react'
import { Link, StaticQuery, graphql } from 'gatsby'
import { linkResolver, withPreview } from '@prismicio/gatsby-source-prismic-graphql'
import { RichText } from 'prismic-reactjs'

const Header = ({ isHomepage }) => {
  const homepageClass = isHomepage ? 'homepage-header' : ''
  return (
    <StaticQuery
      query={`${headerQuery}`}
      render={withPreview((data) => {
        const prismicContent = data.prismic.allNavigations.edges[0]
        if (!prismicContent) return null
        const document = prismicContent.node

        return (
          <header className={`site-header ${homepageClass}`}>
            <Link to="/"><div className="logo">Example Site</div></Link>
            <nav>
              <ul>
                {document.top_navigation.map((navItem, index) => {
                  const linkTo = linkResolver(navItem.link._meta)
                  const linkLabel = RichText.asText(navItem.link_label)
                  return (
                    <li key={`link-${index}`}>
                      <Link to={linkTo}>
                        {linkLabel}
                      </Link>
                    </li>
                  )
                })}
              </ul>
            </nav>
          </header>
        )
      }, headerQuery)}
    />
  )
}

const headerQuery = graphql`
{
  prismic {
    allNavigations {
      edges {
        node {
          top_navigation {
            link {
              ...on PRISMIC_Homepage {
                _meta {
                  type
                }
              }
              ...on PRISMIC_Page {
                _meta {
                  type
                  uid
                }
              }
            }
            link_label
          }
        }
      }
    }
  }
}
`

export default Header

Now when you refresh your site, your top navigation will now pulling its content from Prismic! There are a couple of things to note here: StaticQuery & Link Resolving

StaticQuery

We are using the StaticQuery component rather than the useStaticQuery hook because the hook isn't currently supported in the gastby-source-prismic-graphql plugin that we're using.

You may or may not remember that we added this to our project back in the second article in the series. If it didn't make any sense then, hopefully it is more clear now.

The Link Resolver is a simple function that takes in a Prismic Link field and returns the corresponding url for that page in your site. It lives in src/utils/linkResolver.js in your project and looks like this.

Copy
const linkResolver = (doc) => {
  if (doc.type === 'page') return `/${doc.uid}`
  return '/'
}

export default linkResolver

As you can see here, if the link passed to the Link Resolver is of the type "page", then it will generate the url using the page's UID value (such as '/about' or '/more-info'). Anything else (the homepage) will return the root of the website: '/'.

If you're curious to learn more, check out the Link Resolving article.

Next steps

You're almost done! In the final article of this series, we'll be looking at how to update the project to take advantage of Prismic's Preview feature.

Setting up Previews →