Frameworks

Use Next.js with Prismic

Last updated

Overview

Prismic has a first-party Next.js integration that supports all of Prismic’s features:

Here’s what a Prismic page looks like in Next.js:

app/[uid]/page.tsx
import { SliceZone } from "@prismicio/react";
import { createClient } from "@/prismicio";
import { components } from "@/slices";

export default async function Page({ params }: PageProps<"/[uid]">) {
  // 1. Fetch a page from Prismic
  const { uid } = await params;
  const client = createClient();
  const page = await client.getByUID("page", uid);

  // 2. Display the page's slices
  return <SliceZone slices={page.data.slices} components={components} />;
}

Next.js websites use @prismicio/client, @prismicio/react, and @prismicio/next.

Set up a Next.js website

Prismic can be added to new or existing Next.js websites. Set up your project using the Type Builder, a tool for building by hand, or the Prismic CLI, a tool for AI agents.

Create pages

Content writers create pages from page types, like a homepage, blog post, or landing page. Model page types by hand in the Type Builder, or with the Prismic CLI for AI agents. TypeScript types are generated automatically.

Learn how to create page types

Write page components

Each page type needs a Next.js page component. With file-system-based routing, you create a page file at each page’s path.

The example below shows a page component for a Page page type.

app/[uid]/page.tsx

Define routes

The Prismic CLI keeps routes in prismic.config.json in sync with your page types, whether you model in the Type Builder or with CLI commands.

Page routes are inferred from each page type’s API ID:

  • A page type named Homepage maps to /.
  • A page type named Page maps to /:uid.
  • Any other page type, like Blog Post, maps to /<api-id>/:uid (e.g. /blog-post/:uid).
prismic.config.json
{
  "repositoryName": "example-prismic-repo",
  "routes": [
    { "type": "homepage", "path": "/" },
    { "type": "page", "path": "/:uid" },
    { "type": "blog_post", "path": "/blog/:uid" }
  ]
}

Edit prismic.config.json directly to customize routes. Make sure your routes match your Next.js file-system routes. Here are common examples:

Route resolver pathNext.js file-system route
/app/page.tsx
/:uidapp/[uid]/page.tsx
/blog/:uidapp/blog/[uid]/page.tsx
/:grandparent/:parent/:uidapp/[...path]/page.tsx
Learn more about routes

Create slices

Content writers build pages from reusable sections called slices, like a block of text, a hero, or a call to action. Model slices by hand in the Type Builder, or with the Prismic CLI for AI agents. TypeScript types are generated automatically.

Learn how to create slices

Write React components

The Prismic CLI generates a starter component in src/slices/<SliceName>/index.tsx. Edit the component to add your implementation.

The following example Call to Action component displays a rich text field and a link.

src/slices/CallToAction/index.tsx
import type { Content } from "@prismicio/client";
import { PrismicRichText, type SliceComponentProps } from "@prismicio/react";
import { PrismicNextLink } from "@prismicio/next";

type CallToActionProps = SliceComponentProps<Content.CallToActionSlice>;

export default function CallToAction({ slice }: CallToActionProps) {
  return (
    <section className="flex flex-col gap-4 p-8">
      <PrismicRichText field={slice.primary.text} />
      <PrismicNextLink field={slice.primary.link} className="button" />
    </section>
  );
}

Learn how to display content

Fetch content

Use @prismicio/client and its methods to fetch page content.

The Prismic client

The Prismic CLI creates a prismicio.ts file when you run prismic init. It centralizes your client configuration, including routes and Next.js fetch options.

prismicio.ts

The generated fetchOptions includes the following Next.js cache settings:

  • next.tags: Tags all Prismic API calls with prismic.
  • cache: API calls are cached forever until the prismic tag is revalidated.

Fetch content in pages and slices

Import createClient() from prismicio.ts and create a client. Use the client to fetch content. The following example fetches content for a /[uid] dynamic route.

src/app/[uid]/page.tsx
import type { Metadata } from "next";
import { SliceZone } from "@prismicio/react";
import { createClient } from "@/prismicio";
import { components } from "@/slices";

export default async function Page({ params }: PageProps<"/[uid]">) {
  const { uid } = await params;
  const client = createClient();
  const page = await client.getByUID("page", uid);

  return <SliceZone slices={page.data.slices} components={components} />;
}

You can fetch content in slices the same way. The following example fetches a Settings page.

src/slices/ContactForm/index.tsx
import { Content } from "@prismicio/client";
import { SliceComponentProps } from "@prismicio/react";
import { createClient } from "@/prismicio";

type ContactFormProps = SliceComponentProps<Content.ContactFormSlice>;

export default async function ContactForm({ slice }: ContactFormProps) {
  const client = createClient();
  const settings = await client.getSingle("settings");

  // ...
}

Learn more about fetching content

Fetch new content

You may see stale content as you work on your website. You can fetch new content when working locally by hard-refreshing the page in your browser, usually with Shift+R.

In production, set up content revalidation to fetch new content automatically.

Learn how to set up content revalidation

Secure with an access token

Published content is public by default. You can require a private access token to secure the API.

Learn more about content visibility

  • Generate an access token

    npx prismic token create

    Save the new access token as an environment variable in a .env file.

    .env
    PRISMIC_ACCESS_TOKEN=my-access-token

    Access tokens can also be managed in your repository at SettingsAPI & Security.

  • Pass the access token to your client

    Provide the token via the accessToken option in prismicio.ts:

    prismicio.ts
    export const createClient = (config: ClientConfig = {}) => {
      const client = baseCreateClient(repositoryName, {
        accessToken: process.env.PRISMIC_ACCESS_TOKEN, 
        routes: prismicConfig.routes,
        fetchOptions: {
          next: { tags: ["prismic"] },
          cache: "force-cache",
        },
        ...config,
      });
    
      enableAutoPreviews({ client });
    
      return client;
    };
  • Change your repository’s API access

    Set the API access to private. Content API requests will immediately require an access token.

    npx prismic repo set-api-access private

    API visibility can also be managed in your repository at SettingsAPI & Security.

Display content

Display content using @prismicio/react and @prismicio/next. Here are the most commonly used components:

Learn how to display content from a field

Live previews in the Page Builder

The Page Builder shows live-updating thumbnails for each slice as content writers edit.

A screenshot of a page with live previews in the Page Builder.

A page with live previews in the Page Builder.

Live previews are powered by the slice simulator, a special route that renders individual slices. The Prismic CLI creates the simulator page at app/slice-simulator/page.tsx when you run prismic init.

Tell Prismic where your simulator is running so the Page Builder can load it:

npx prismic preview set-simulator http://localhost:3000

The simulator URL can also be set from any document. Click the ”” button next to the Publish/Unpublish button in the top-right corner and select Live preview settings.

Once your website is deployed, update the simulator URL to your production domain.

Preview draft content

Full-website previews let content writers see draft content on your website before publishing. The prismic init command creates the needed routes during setup: /api/preview starts a draft preview session, and /api/exit-preview ends it.

Add a development preview URL so you can preview drafts locally:

npx prismic preview add http://localhost:3000/api/preview --name Development

Once deployed, add your production URL as a second preview. Previews can also be managed at SettingsPreviews.

Deploy

Deploy your Next.js website with your hosting provider:

Handle content changes

The prismic init command creates a /api/revalidate Route Handler that clears the Next.js cache when content changes in Prismic.

Register the endpoint as a webhook so Prismic calls it when content is published or unpublished. You do not need to set up a webhook with your hosting provider.

npx prismic webhook create https://example.com/api/revalidate \
  --trigger documentsPublished \
  --trigger documentsUnpublished

Webhooks can also be managed at SettingsWebhooks.

SEO

Internationalization

Prismic supports multi-lingual websites. See Locales for details on locale management.

Was this page helpful?