Navbars, Footers, and Menus

For menus or footers, you'll query the menu on every page; we'll show you the best practice for doing this below. This example is based on our full sample project.


Model the menu in Prismic

In this example, we have created a Single type Custom Type for the menu as we will be creating one version of the document. We have a Title field and a Group field inside the menu type.

In the Group field, we added a Link field and a Rich Text field, this way you can add as many links as you need. From here you can create a new menu document in your dashboard and add your content.

In your customtypes folder add a folder called menu, then copy and paste this JSON into a file called index.js (You'll see it once you refresh Slice Machine):

Copy
{
  "id": "menu",
  "label": "Menu",
  "repeatable": false,
  "json": {
    "Main": {
      "title": {
        "type": "StructuredText",
        "config": {
          "placeholder": "Menu title...",
          "single": "heading1"
        }
      },
      "menuLinks": {
        "type": "Group",
        "config": {
          "label": "Menu Links",
          "placeholder": "",
          "fields": {
            "label": {
              "type": "StructuredText",
              "config": {
                "single": "paragraph",
                "label": "Link Label",
                "placeholder": "Link Label..."
              }
            },
            "link": {
              "type": "Link",
              "config": {
                "label": "Link",
                "placeholder": "Select a Link..."
              }
            }
          }
        }
      }
    }
  }
}

Query the menu

For menu documents to work with Prismic content previews you'll need to query the menu on every page so it can be accessed with Next.js' preview mode. Normally this would make queries larger, but with Static Site Generation this shouldn't be an issue.

The query in the example below for the single instance of the Custom Type "menu" uses the query helper function getSingle from the react development kit. Then, pass the menu as props to the <Layout /> component in the render method.

Copy
// ~/pages/[uid].js

import { SliceZone } from "@prismicio/react";
import * as prismicH from "@prismicio/helpers";

import { createClient, linkResolver } from "../prismicio";
import { components } from "../slices";
import { Layout } from "../components/Layout";

const Page = ({ menu, slices }) => {
  return (
    <Layout menu={menu}>
      <SliceZone slices={slices} components={components} />
    </Layout>
  );
};

export async function getStaticProps({ params, previewData }) {
  const client = createClient({ previewData });

  const menu = await client.getSingle("menu");
  const page = await client.getByUID("page", params.uid);

  return {
    props: {
      menu,
      slices: page.data.slices,
    },
  };
}

export async function getStaticPaths() {
  const client = createClient();

  const pages = await client.getAllByType("page");

  return {
    paths: pages.map((page) => prismicH.asLink(page, linkResolver)),
    fallback: false,
  };
}

export default Page;

Create the components

Create a /components folder in your Next.js project and add these files inside of it:

  • Layout.js
  • Header.js

Create a Layout

In the Layout.js file, retrieve the menu from the props in this file and pass it to the Header.js component. Make sure that all the imports match your project routes.

Copy
import Head from "next/head";

import { Header } from "./Header";

export const Layout = ({ children, menu }) => {
  return (
    <div className="text-neutral-700 antialiased">
      <Head>
        <title> Prismic Next.js Multi Page Website </title>
      </Head>
      <Header menu={menu} />
      <main>{children}</main>
    </div>
  );
};

Create a header

In your Header.js file, access the menuLinks props from Layout.js and use them to create the menu. In this file, the menuLinks array, which was passed as props, is mapped and each link is passed through the PrismicLink component and linkResolver() function which is defined in the prismicio.js file.

Copy
import { PrismicLink, PrismicText } from "@prismicio/react";

export const Header = ({ menu }) => (
  <header className="relative -mb-px border-b border-neutral-200 bg-white px-6 py-4">
    <div className="mx-auto flex max-w-5xl items-baseline md:items-center">
      <PrismicLink href="/" className="relative -m-4 p-4 text-xl font-black">
        <PrismicText field={menu.data?.title} />
      </PrismicLink>
      <nav className="flex-grow">
        <ul className="-ml-5 -mt-5 flex justify-end">
          {menu.data?.menuLinks.map((menuLink) => (
            <li key={menuLink.label} className="pt-5 pl-5">
              <PrismicLink field={menuLink.link} className="text-neutral-500">
                <PrismicText field={menuLink.label} />
              </PrismicLink>
            </li>
          ))}
        </ul>
      </nav>
    </div>
  </header>
);

That's it, now you have a project with a menu that you can modify to your liking.


Related articles


Was this article helpful?
Not really
Yes, Thanks

Can't find what you're looking for? Spot an error in the documentation? Get in touch with us on our Community Forum or using the feedback form above.