Taxonomies

Learn how to create taxonomies with Next.js an Prismic.

Taxonomies define how you organize content. Categories are a common form of taxonomy. This guide describes a scalable way to create a category taxonomy within Prismic using content relationships. Content relationships allow you to link between Prismic documents and retrieve data. You will be able to template a list of all categories, a list of categories used in a page, and display a page’s categories.


The content models you’ll build throughout this guide support the following key features:

  • Manage your categories in Prismic. Content managers will be able to add, edit, and remove categories from documents. They can also create and delete categories.
  • Reuse your categories in multiple contexts. A list of links displayed on the blog page, for example, could be reused in posts with different styling.
  • Add multiple categories to your documents. A blog post having multiple categories is a common strategy to group similar posts.

Prerequisites

To follow this tutorial, you should have: a Next.js project with Slice Machine, which has at least one page type and one page.

Don’t have a project? Launch our minimal starter to get started.

Define a “category” custom type

First, open Slice Machine, and create a reusable custom type called “Category”. Then, create a rich text field to store the category name.

CategorycategoryCustom Type
  • Static Zone
    • UIDuidUID
    • NamenameRich Text

Add a “categories” field to page types

In the page type you want to add a category to, create a repeatable group field. The repeatable group field will allow your content authors to select as many categories as they need.

PostpostCustom Type
  • Static Zone
    • UIDuidUID
    • CategoriescategoriesGroup
      • CategorycategoryContent Relationship

Next, create a content relationship field inside the repeatable group field, restricted to the category page type. The content relationship field will allow content authors to link to categories.

Slice Machine content relationship field settings

Create your first “category”

Open the Page Builder and create a categories document with the category name. Create a document for every category.

Category document in Page Builder

Add categories to pages

To add categories to your pages, select the relevant categories in the content relationship fields.

Post document in Page Builder

Define a category route

To create a route for the Categories custom type, add the following to the routes array in prismicio.js:

{
  type: 'category',
  path: '/categories/:uid',
}

Display a list of all categories

To create a list of every category, query by the category custom type.

client.getAllByType("category");

Then you can template the list of all categories to display on your page.

app/page.js
import { PrismicNextLink } from "@prismicio/next";
import { PrismicText } from "@prismicio/react";
import { createClient } from "@/prismicio";

export default async function Home() {
  const client = createClient();
  const categories = await client.getAllByType("category");

  return (
    <main>
      <ul>
        {categories.map((category) => {
          return (
            <li key={category.id}>
              <PrismicNextLink document={category}>
                <PrismicText field={category.data.name} />
              </PrismicNextLink>
            </li>
          );
        })}
      </ul>
    </main>
  );
}

Display a page’s categories

To display a page’s categories, in page.js, query the content relationship field in the page. Use fetchLinks to fetch data in the linked categories. Then you can template the list of categories used in the page to display on the page.

app/page.js
import { PrismicNextLink } from "@prismicio/next";
import { PrismicText } from "@prismicio/react";
import { createClient } from "@/prismicio";

export default async function Post({ params }) {
  const client = createClient();
  const post = await client.getByUID("post", params.uid, {
    fetchLinks: ["category.name"],
  });

  return (
    <main>
      <ul>
        {post.data.categories.map((category) => {
          return (
            <li key={category.id}>
              <PrismicNextLink document={category}>
                <PrismicRichText
                  field={category.data.name}
                />
              </PrismicNextLink>
            </li>
          );
        })}
      </ul>
    </main>
  );
}

export async function generateStaticParams() {
  const client = createClient();
  const posts = await client.getAllByType("post");

  return posts.map((post) => {
    return { uid: post.uid };
  });
}

Display a list of pages in each category

To create a page for each category, in the app directory, create a file at app/category/[uid]/page.js.

To create a list of pages in a category, in page.js, retrieve the category ID for the category you wish to filter for by using client.getByUID().

Then query all documents with the page type you wish to display and use the at() filter with the IDs of the page type, group field, content relationship, and category, like this:

prismic.filter.at('my.example_page_type.example_group.example_content_relationship', example_category_id).

Finally, you can template the list of pages with a specific category to display on your page.

app/category/[uid]/page.js
import { PrismicNextLink } from "@prismicio/next";
import { createClient } from "@/prismicio";
import * as prismic from "@prismicio/client";

export default async function Category({ params }) {
  const client = createClient();

  // Query the specific category
  const category = await client.getByUID(
    "category",
    params.uid,
  );

  // Use the category ID to filter for posts with that category
  const pagesInCategory = await client.getAllByType(
    "post",
    {
      filters: [
        prismic.filter.at(
          "my.post.categories.category",
          category.id,
        ),
      ],
    },
  );

  return (
    <main>
      <ul>
        {pagesInCategory.map((page) => {
          return (
            <li key={pages.id}>
              <PrismicNextLink document={page}>
                {page.data.meta_title}
              </PrismicNextLink>
            </li>
          );
        })}
      </ul>
    </main>
  );
}

export async function generateStaticParams() {
  const client = createClient();
  const categories = await client.getAllByType("category");

  return categories.map((category) => {
    return { uid: category.uid };
  });
}

Going further

The taxonomy strategy shared in this article can be used as-is or as a base for your own custom taxonomy strategy.

Here are a few ideas you can try to customize your taxonomies:

  • Create a page to list all of your categories
  • Allow content managers to select an image for their categories and display them in the category list
  • Support short descriptions for categories
  • Create child categories
  • Create an “author” type for your pages