---
title: "Use Next.js with Prismic"
description: "Learn how to build websites with Next.js and Prismic."
category: "frameworks"
audience: developers
lastUpdated: "2026-02-13T08:29:16.000Z"
---

> This guide uses the [Data Cache](https://nextjs.org/docs/app/guides/caching#data-cache). Prismic also supports the [Pages Router](https://prismic.io/docs/nextjs/pages.md) for legacy websites.

# Overview

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

* Model content with [slices](https://prismic.io/docs/slices.md) and [page types](https://prismic.io/docs/content-modeling.md#page-types) using [Slice Machine](https://prismic.io/docs/slice-machine.md).
* Fetch and display content using [SDKs](https://prismic.io/docs/apis.md) with generated [TypeScript](https://www.typescriptlang.org/) types.
* Preview draft content with [live previews](https://prismic.io/docs/previews.md#live-previews) and [full-website previews](https://prismic.io/docs/previews.md#full-website-previews).

Here's what a Prismic page looks like in Next.js with the Data Cache:

```tsx filename=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](https://prismic.io/docs/technical-reference/prismicio-client/v7.md), [@prismicio/react](https://prismic.io/docs/technical-reference/prismicio-react/v3.md), and [@prismicio/next](https://prismic.io/docs/technical-reference/prismicio-next/v2.md).

# Set up a Next.js website

Prismic can be added to new or existing Next.js websites. Follow these steps to set up a Next.js project.

1. **Create a Prismic repository**

   From the [Prismic dashboard](https://prismic.io/dashboard), create a Prismic repository. Select **Next.js**.

   When asked to select a starter, select **Connect your own web app**.

   If you prefer starting with a template, select **Minimal starter** or **Full website demo** instead.

2. **Set up a Next.js project**

   Follow the setup instructions shown in your Prismic repository.

   The instructions guide you through creating a new Next.js project (if needed) and adding Prismic using `@slicemachine/init`.

   The `@slicemachine/init` command installs Prismic's packages and configures your project with a [Prismic client](#fetch-content), [content previews](#live-previews-in-the-page-builder), and [revalidation](#handle-content-changes).

3. **Set up content previews**

   Content writers can preview content on your website before publishing.

   `@slicemachine/init` performs most of the setup for you. However, there are a few steps to complete manually.

   [See the preview setup instructions](#live-previews-in-the-page-builder)

4. **Start building with Prismic**

   Your Next.js website is now ready for Prismic. Next, learn how to [create pages](#create-pages) and [slices](#create-slices).

> **Important**
>
> <CalloutHeading>Help us improve the setup process</CalloutHeading>
>
> Tell us what worked and where setup slowed you down — and earn $50.
>
> <TrackCTA type="primary" position="activation-recruitment" asChild>
>   <CalloutButton color="purple" startIcon={<MessageSquareTextIcon />} href="https://docs.google.com/forms/d/e/1FAIpQLSfblSNBRfXB4Tb5QwFPJ4tp_GZseZ9aBDuzk07YuzisVhOF3A/viewform">
>     Share your experience
>   </CalloutButton>
> </TrackCTA>

# Create pages

Website pages are managed in Prismic using [page types](https://prismic.io/docs/content-modeling.md#page-types). Page types are created in [Slice Machine](https://prismic.io/docs/slice-machine.md).

[Learn how to create page types](https://prismic.io/docs/content-modeling.md#how-to-create-a-page-type)

## Write page components

Each page type needs a Next.js page component. With the App Router's file-system based routing, you create a [page file](https://nextjs.org/docs/app/api-reference/file-conventions/page) at each page's path.

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

```tsx filename=app/[uid]/page.tsx collapsed
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} />;
}

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

  return {
    title: page.data.meta_title,
    description: page.data.meta_description,
    openGraph: {
      images: [{ url: page.data.meta_image.url ?? "" }],
    },
  };
}

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

  return pages.map((page) => ({ uid: page.uid }));
}
```

> You can also find this code snippet customized for your page type in Slice Machine. Learn more in the [Content Modeling](https://prismic.io/docs/content-modeling.md#create-a-page-file) page.

## Define routes

Prismic needs to know your website's routes to fill in link URLs. Configure the `routes` constant in your project's `prismicio.ts` with a set of [route resolvers](https://prismic.io/docs/route-resolver.md).

This example includes routes for a homepage, general pages, and a blog.

```ts filename=prismicio.ts
// `type` is the API ID of a page type.
// `path` determines the URL for a page of that type.
const routes: Route[] = [
  { type: "homepage", path: "/" },
  { type: "page", path: "/:uid" },
  { type: "blog_post", path: "/blog/:uid" },
];
```

Your route resolvers should match your Next.js file-system-based routes. Here are some commonly used routes:

| Route resolver path          | Next.js file-system route |
| ---------------------------- | ------------------------- |
| `/`                          | `app/page.tsx`            |
| `/:uid`                      | `app/[uid]/page.tsx`      |
| `/blog/:uid`                 | `app/blog/[uid]/page.tsx` |
| `/:grandparent/:parent/:uid` | `app/[...path]/page.tsx`  |

[Learn more about route resolvers](https://prismic.io/docs/route-resolver.md)

# Create slices

Page content is written using reusable page sections called [slices](https://prismic.io/docs/slices.md). Slices are created in [Slice Machine](https://prismic.io/docs/slice-machine.md).

[Learn how to create slices](https://prismic.io/docs/slices.md#how-to-create-a-slice)

## Write React components

Slice Machine generates a bootstrapped React component when a slice is created. You can find the generated files in `src/slices` or whichever [slice library](https://prismic.io/docs/slices.md#slice-libraries) was selected.

Once your slice is [configured with fields](https://prismic.io/docs/slices.md#model-your-content), edit the slice's `index.tsx` file to display the slice's content.

Here is an example of a **Call to Action** slice. It displays a rich text field and a link field.

```tsx filename=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](#display-content)

# Fetch content

Use [`@prismicio/client`](https://prismic.io/docs/technical-reference/prismicio-client.md) and its methods to fetch page content.

## Set up a Prismic client

Create a `prismicio.ts` file to centralize your Prismic client setup. This file contains [route resolvers](https://prismic.io/docs/route-resolver.md) and default Prismic client settings.

The `fetch` cache is configured using the client's `fetchOptions`.

```ts filename=prismicio.ts {21-24}
import {
  createClient as baseCreateClient,
  type ClientConfig,
  type Route,
} from "@prismicio/client";
import { enableAutoPreviews } from "@prismicio/next";
import sm from "../slicemachine.config.json";

export const repositoryName = sm.repositoryName;

// TODO: Update with your route resolvers.
const routes: Route[] = [
  { type: "homepage", path: "/" },
  { type: "page", path: "/:uid" },
  { type: "blog_post", path: "/blog/:uid" },
];

export function createClient(config: ClientConfig = {}) {
  const client = baseCreateClient(repositoryName, {
    routes,
    fetchOptions: {
      next: { tags: ["prismic"] },
      cache: "force-cache",
    },
    ...config,
  });

  enableAutoPreviews({ client });

  return client;
}
```

The above `fetchOptions` includes the following [Next.js cache settings](https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options):

* `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.

This example page fetches content for a `/[uid]` dynamic route.

```ts filename=src/app/[uid]/page.tsx {3,10-12}
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;
  // Caching is configured via fetchOptions in prismicio.ts.
  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. This example fetches a Settings page.

```ts filename=src/slices/ContactForm/index.tsx {3,8-9}
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](https://prismic.io/docs/fetch-content.md)

## Fetch new content

When pages are cached with `fetchOptions`, 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. In Chrome, you can hard-refresh using <Kbd>Shift+<KbdMod />R</Kbd>.

In production, you will need to set up content revalidation to fetch new content.

[Learn how to set up content revalidation](#handle-content-changes)

## 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](https://prismic.io/docs/fetch-content.md#content-visibility)

1. **Open your API & Security settings**

   Navigate to your Prismic repository and go to **Settings** > **API & Security**.

2. **Change the API access**

   Under the **Repository security** section, change the **API access** dropdown to "Private API."

   Click **Change the API visibility**.

3. **Generate an access token**

   Under the **Generate an Access Token** section, fill out the form.

   | Field            | Value                            |
   | ---------------- | -------------------------------- |
   | **Name**         | A name to identify your website. |
   | **Callback URL** | Leave blank.                     |

   Click **Add this application**.

4. **Pass the access token to your client**

   Save the access token as an environment variable in a [`.env`](https://nextjs.org/docs/app/guides/environment-variables) file.

   ```sh filename=.env
   PRISMIC_ACCESS_TOKEN=my-access-token
   ```

   Then, pass the access token to the client in `prismicio.ts`.

   ```ts filename=prismicio.ts
   export function createClient(config: ClientConfig = {}) {
     const client = baseCreateClient(repositoryName, {
       accessToken: process.env.PRISMIC_ACCESS_TOKEN, // [!code ++]
       routes,
       ...config,
     });

     enableAutoPreviews({ client });

     return client;
   }
   ```

   The Client ID and Secret values on the API & Security page can be ignored.

> **Important**
>
> The access token is a secret. Do not use it in client-side requests to prevent exposing the token.

# Display content

Prismic content can be displayed using [`@prismicio/react`](https://prismic.io/docs/technical-reference/prismicio-react/v3.md) and [`@prismicio/next`](https://prismic.io/docs/technical-reference/prismicio-next/v2.md).

Here are the most commonly used components in Next.js websites:

* [`<PrismicNextLink>`](https://prismic.io/docs/technical-reference/prismicio-next/v2.md#prismicnextlink) - Display links using [`next/link`](https://nextjs.org/docs/app/api-reference/components/link).
* [`<PrismicNextImage>`](https://prismic.io/docs/technical-reference/prismicio-next/v2.md#prismicnextimage) - Display images using [`next/image`](https://nextjs.org/docs/app/api-reference/components/image).
* [`<PrismicRichText>`](https://prismic.io/docs/technical-reference/prismicio-react/v3.md#prismicrichtext) - Display rich text.
* [`<PrismicText>`](https://prismic.io/docs/technical-reference/prismicio-react/v3.md#prismictext) - Display plain text.
* [`<SliceZone>`](https://prismic.io/docs/technical-reference/prismicio-react/v3.md#slicezone) - Display slices.

[Learn how to display content from a field](https://prismic.io/docs/fields.md)

# Live previews in the Page Builder

Content writers can preview content live while editing in the [Page Builder](https://prismic.io/docs/previews.md#live-previews). Each [slice](https://prismic.io/docs/slices.md) in a page is shown as a live-updating thumbnail.

## Set up live previewing

Live previews require a special `/slice-simulator` route in your Next.js website.

1. **Add `/slice-simulator`**

   Create a file at `app/slice-simulator/page.tsx` with the following contents.

   ```tsx filename=app/slice-simulator/page.tsx
   import {
     SliceSimulator,
     SliceSimulatorParams,
     getSlices,
   } from "@prismicio/next";
   import { SliceZone } from "@prismicio/react";
   import { components } from "@/slices";

   export default async function SliceSimulatorPage({
     searchParams,
   }: SliceSimulatorParams) {
     const { state } = await searchParams;
     const slices = getSlices(state);

     return (
       <SliceSimulator>
         <SliceZone slices={slices} components={components} />
       </SliceSimulator>
     );
   }
   ```

2. **Set the simulator URL in the Page Builder**

   Navigate to your Prismic repository and open a page.

   Click the "**...**" button next to the **Publish**/**Unpublish** button in the top-right corner. Select **Live preview settings**.

   In the modal, enter `http://localhost:3000/slice-simulator` and click **Save**.

   > Once your website is deployed, change the live preview URL to your production domain.

# Preview draft content

Content writers can preview content on your website before publishing.

`@slicemachine/init` performs most of the setup for you during [project setup](#set-up-a-nextjs-project). However, there are a few steps to complete manually.

## Set up previews in Next.js

[`@prismicio/next`](https://prismic.io/docs/technical-reference/prismicio-next/v2.md) provides helpers and a component to support [content previews](https://prismic.io/docs/previews.md#full-website-previews).

1. **Add `<PrismicPreview>` to `app/layout.tsx`**

   [`<PrismicPreview>`](https://prismic.io/docs/technical-reference/prismicio-next/v2.md#prismicpreview) adds the Prismic toolbar and event listeners. The website automatically refreshes when a content draft is saved.

   ```tsx filename=app/layout.tsx {2,3,9}
   import { type ReactNode } from "react";
   import { PrismicPreview } from "@prismicio/next";
   import { repositoryName } from "@/prismicio";

   export default function RootLayout({ children }: { children: ReactNode }) {
     return (
       <html lang="en">
         <body>{children}</body>
         <PrismicPreview repositoryName={repositoryName} />
       </html>
     );
   }
   ```

2. **Call `enableAutoPreviews()` with your Prismic client**

   [`enableAutoPreviews()`](https://prismic.io/docs/technical-reference/prismicio-next/v2.md#enableautopreviews) configures a Prismic client to automatically fetch draft content during a preview. Include it in your [`prismicio.ts`](#set-up-a-prismic-client) file.

   ```tsx filename=prismicio.ts {5,13}
   import {
     createClient as baseCreateClient,
     ClientConfig,
   } from "@prismicio/client";
   import { enableAutoPreviews } from "@prismicio/next";
   import sm from "../slicemachine.config.json";

   export const repositoryName = sm.repositoryName;

   export function createClient(config: ClientConfig = {}) {
     const client = baseCreateClient(repositoryName, config);

     enableAutoPreviews({ client });

     return client;
   }
   ```

3. **Create an `/api/preview` endpoint**

   This endpoint enables [Draft Mode](https://nextjs.org/docs/app/building-your-application/configuring/draft-mode) and redirects a content writer to the previewed page. It uses [`redirectToPreviewURL()`](https://prismic.io/docs/technical-reference/prismicio-next/v2.md#redirecttopreviewurl).

   ```tsx filename=app/api/preview/route.ts {2,8}
   import { NextRequest } from "next/server";
   import { redirectToPreviewURL } from "@prismicio/next";
   import { createClient } from "@/prismicio";

   export async function GET(request: NextRequest) {
     const client = createClient();

     return await redirectToPreviewURL({ client, request });
   }
   ```

4. **Create an `/api/exit-preview` endpoint**

   This endpoint ends a preview session. It is called by the Prismic toolbar when closing a preview. It uses [`exitPreview()`](https://prismic.io/docs/technical-reference/prismicio-next/v2.md#exitpreview).

   ```tsx filename=app/api/exit-preview/route.ts {1,4}
   import { exitPreview } from "@prismicio/next";

   export function GET() {
     return exitPreview();
   }
   ```

## Set up previews in Prismic

After setting up [previews in your Next.js project](#set-up-previews-in-nextjs), set up previews in Prismic.

1. **Open your preview settings**

   Navigate to your Prismic repository and go to **Settings** > **Previews**.

2. **Create a preview**

   In the **Manage your previews** section, create a preview using the following values:

   | Field                           | Value                   |
   | ------------------------------- | ----------------------- |
   | **Site name**                   | Development             |
   | **Domain for your application** | `http://localhost:3000` |
   | **Preview route**               | `/api/preview`          |

   Click **Create my preview**.

   > Once your website is deployed, add another preview with your production domain.

# Deploy

To deploy your website, follow the instructions for deploying Next.js with your chosen hosting provider:

* [Vercel](https://vercel.com/guides/deploying-nextjs-with-vercel)
* [Netlify](https://docs.netlify.com/welcome/add-new-site/)
* [AWS Amplify](https://docs.amplify.aws/nextjs/build-a-backend/)
* [Cloudflare](https://opennext.js.org/cloudflare)

## Handle content changes

Your app needs to be notified when content changes in Prismic.

1. **Create a `/api/revalidate` Route Handler**

   Add the following `/api/revalidate` Route Handler to your Next.js app. It clears the Next.js cache when content changes in Prismic.

   ```tsx filename=app/api/revalidate/route.ts {5}
   import { NextResponse } from "next/server";
   import { revalidateTag } from "next/cache";

   export async function POST() {
     revalidateTag("prismic", "max");

     return NextResponse.json({ revalidated: true, now: Date.now() });
   }
   ```

   The `"prismic"` tag matches the tag used in [page components](#write-page-components) and [the Prismic client](#set-up-a-prismic-client). When `revalidateTag()` is called, Next.js clears all cache entries with this tag.

2. **Create a webhook**

   Add a Prismic webhook that is called when content changes in Prismic.

   Follow the [Create a webhook](https://prismic.io/docs/webhooks.md#create-a-webhook) instructions in our webhooks documentation using these values:

   | Field        | Value                                                                                   |
   | ------------ | --------------------------------------------------------------------------------------- |
   | **Name**     | "Display published content"                                                             |
   | **URL**      | Your app's deployed URL + `/api/revalidate` (e.g `https://example.com/api/revalidate`). |
   | **Triggers** | Only check "A page is published" and "A page is unpublished".                           |

   You do not need to set up a webhook with your hosting provider.

# SEO

Prismic websites can be optimized for search engines using `meta_title` and `meta_descriptions` fields. These fields provide metadata and may improve your website's ranking.

1. **Add SEO fields to your page types**

   SEO fields are added to page types by default in an **SEO** tab.

   If your page type does not have this tab, create a tab named **SEO** and add the following fields:

   | Label            | API ID             | Type      | Description                              |
   | ---------------- | ------------------ | --------- | ---------------------------------------- |
   | Meta Title       | `meta_title`       | Rich Text | The title shown in search results.       |
   | Meta Description | `meta_description` | Text      | The description shown in search results. |
   | Meta Image       | `meta_image`       | Image     | The image shown in link previews.        |

   > When using the `meta_title` and `meta_description` field API IDs, the [Page Builder](https://prismic.io/docs/guides/page-builder.md) shows a preview of your page in search results.

   The `meta_image` field is not typically used by search engines, but it can be used as a preview when linking to your website on some platforms.

2. **Add metadata to pages**

   Use the metadata fields in a `page.tsx`'s [`generateMetadata`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata) function.

   ```ts filename=app/[uid]/page.tsx {12-18}
   import type { Metadata } from "next";
   import { asImageSrc } from "@prismicio/client";
   import { createClient } from "@/prismicio";

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

     return {
       title: page.data.meta_title,
       description: page.data.meta_description,
       openGraph: {
         images: [{ url: asImageSrc(page.data.meta_image) ?? "" }],
       },
     };
   }
   ```

# Internationalization

Prismic supports websites with multiple languages.

To learn more about Prismic's locale management, see [Locales](https://prismic.io/docs/languages-locales.md).

> This guide is based on the official [Next.js internationalization guide](https://nextjs.org/docs/app/building-your-application/routing/internationalization).

1. **Install the necessary packages**

   The `negotiator` and `@formatjs/intl-localematcher` packages are needed to support internationalization.

   ```sh
   npm install negotiator @formatjs/intl-localematcher
   ```

2. **Create an `i18n.ts` file**

   The `i18n.ts` file provides a set of internationalization helpers. The helpers will be used in your website's [Proxy](https://nextjs.org/docs/app/getting-started/proxy).

   Create an `i18n.ts` file next to to your `app` directory with the following contents.

   ```ts filename=i18n.ts
   import type { NextRequest } from "next/server";
   import { match } from "@formatjs/intl-localematcher";
   import Negotiator from "negotiator";

   /**
    * A record of locales mapped to a version displayed in URLs. The first entry is
    * used as the default locale.
    */
   // TODO: Update this object with your website's supported locales. Keys
   // should be the locale IDs registered in your Prismic repository, and values
   // should be the string that appears in the URL.
   const LOCALES = {
     "en-us": "en-us",
     "fr-fr": "fr-fr",
   };

   /** Creates a redirect with an auto-detected locale prepended to the URL. */
   export function createLocaleRedirect(request: NextRequest): Response {
     const headers = {
       "accept-language": request.headers.get("accept-language"),
     };
     const languages = new Negotiator({ headers }).languages();
     const locales = Object.keys(LOCALES);
     const locale = match(languages, locales, locales[0]);

     request.nextUrl.pathname = `/${LOCALES[locale]}${request.nextUrl.pathname}`;

     return Response.redirect(request.nextUrl);
   }

   /** Determines if a pathname has a locale as its first segment. */
   export function pathnameHasLocale(request: NextRequest): boolean {
     const regexp = new RegExp(`^/(${Object.values(LOCALES).join("|")})(\/|$)`);

     return regexp.test(request.nextUrl.pathname);
   }

   /**
    * Returns the full locale of a given locale. It returns `undefined` if the
    * locale is not in the master list.
    */
   export function reverseLocaleLookup(locale: string): string | undefined {
     for (const key in LOCALES) {
       if (LOCALES[key] === locale) {
         return key;
       }
     }
   }
   ```

3. **Define locales in `i18n.ts`**

   `i18n.ts` contains a list of locales supported by your website.

   Update the `LOCALES` constant to match your Prismic repository's locales. The first locale is used when a visitor's locale is not supported.

   ```ts filename=i18n.ts
   const LOCALES = {
     "en-us": "en-us",
     "fr-fr": "fr-fr",
   };
   ```

   You can define how the locale appears in the URL by changing the object's values. In the following example, the `en-us` locale will appear as `en` in the URL (e.g. `/en/about`).

   ```ts filename=i18n.ts {2-3}
   const LOCALES = {
     "en-us": "en",
     "fr-fr": "fr",
   };
   ```

   > Statically defining your locales avoids a Prismic API call, optimizing your website's performance.

4. **Create or modify `proxy.ts`**

   > This file is called `middleware.ts` in Next.js v15 and earlier.

   Website visitors will be directed to the correct locale using [Proxy](https://nextjs.org/docs/app/getting-started/proxy).

   Create a `proxy.ts` file with the following contents, or modify your existing `proxy.ts` to include the highlighted lines.

   ```ts filename=proxy.ts {2,5-7}
   import type { NextRequest } from "next/server";
   import { createLocaleRedirect, pathnameHasLocale } from "@/i18n";

   export function proxy(request: NextRequest) {
     if (!pathnameHasLocale(request)) {
       return createLocaleRedirect(request);
     }
   }

   export const config = {
     matcher: ["/((?!_next|api|slice-simulator|icon.svg).*)"],
   };
   ```

   [Learn more about Proxy](https://nextjs.org/docs/app/getting-started/proxy)

5. **Nest routes under a `[lang]` dynamic route segment**

   Create a directory at `app/[lang]` and nest all other routes under this directory.

   The `lang` route parameter will contain the visitor's locale. For example, `/en-us/about` sets `lang` to `"en-us"`.

   [Learn about Next.js dynamic routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes)

6. **Fetch content from the visitor's locale**

   In your `page.tsx` files, forward the `lang` parameter to your Prismic query.

   ```ts filename=app/[lang]/[uid]/page.tsx {2,9}
   import { createClient } from "@/prismicio";
   import { reverseLocaleLookup } from "@/i18n";

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

     const client = createClient();
     const page = await client.getByUID("page", uid, {
       lang: reverseLocaleLookup(lang),
     });

     // ...
   }
   ```

   The `reverseLocaleLookup` helper from `i18n.ts` converts a shortened locale (e.g. `en`) to its full version (e.g. `en-us`).

7. **Fetch all locales in `generateStaticParams`**

   > This step is needed if you statically build pages using [`generateStaticParams`](https://nextjs.org/docs/app/api-reference/functions/generate-static-params), which we recommend.

   Fetch pages from all locales using the Prismic client's `lang: "*"` option. Include the `lang` route parameter.

   ```ts filename=app/[lang]/[uid]/page.tsx {4,9}
   export async function generateStaticParams() {
     const client = createClient();
     const pages = await client.getAllByType("page", {
       lang: "*",
     });

     return pages.map((page) => ({
       lang: page.lang,
       uid: page.uid,
     }));
   }
   ```

# Configure Slice Machine

Slice Machine can be configured in `slicemachine.config.json`. Add options to the `adapter.options` property.

```json filename=slicemachine.config.json {7-9}
{
  "repositoryName": "example-prismic-repo",
  "libraries": ["./src/slices"],
  "localSliceSimulatorURL": "http://localhost:3000/slice-simulator",
  "adapter": {
    "resolve": "@slicemachine/adapter-next",
    "options": {
      "typescript": true
    }
  }
}
```

| Property                               | Type    | Description                                                                                                                                          | Default                                                            |
| -------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| format (optional)                      | boolean | Determines if generated files are formatted using [Prettier](https://prettier.io/).                                                                  | `true`                                                             |
| lazyLoadSlices (optional)              | boolean | Determines if slice components are lazy loaded with [`next/dynamic`](https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading). | `true`                                                             |
| typescript (optional)                  | boolean | Determines if generated files are written in TypeScript or JavaScript.                                                                               | `true` if a project has a `tsconfig.json` file, `false` otherwise. |
| jsxExtension (optional)                | boolean | Determines if generated JavaScript files should use a `.jsx` file extension. Has no effect when TypeScript is used.                                  | `false`                                                            |
| generatedTypesFilePath (optional)      | string  | The filepath at which generated TypeScript types will be saved.                                                                                      | `prismicio-types.d.ts`                                             |
| environmentVariableFilePath (optional) | string  | The filepath at which the active Prismic [environment](https://prismic.io/docs/environments.md) is stored as an environment variable.                | `.env.local`                                                       |
