*** title: Next.js SDK description: >- Integrate feature flags in your Next.js applications using the Unleash Next.js SDK 'og:site\_name': Unleash 'og:title': Next.js SDK keywords: 'Next.js SDK, React SDK, feature flags, server-side rendering, SSR, SSG' max-toc-depth: 3 ---------------- This [Next.js](https://nextjs.org/) SDK is designed to help you integrate with Unleash and evaluate feature flags inside your application. You can use this client with [Unleash Enterprise](https://www.getunleash.io/pricing?utm_source=readme\&utm_medium=nextjs) or [Unleash Open Source](https://github.com/Unleash/unleash). ## Setup ### Installation To install, simply run: ```sh npm install @unleash/nextjs # or yarn add @unleash/nextjs # or pnpm add @unleash/nextjs ``` There is an [`./example`](https://github.com/Unleash/unleash-nextjs-sdk/blob/main/./example) project that you can [deploy to Vercel](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FUnleash%2Funleash-nextjs-sdk%2Ftree%2Fmain%2Fexample) or [edit in CodeSandbox](https://codesandbox.io/s/github/Unleash/unleash-nextjs-sdk/tree/main/example). ### Environment Variables This package will attempt to load configuration from [Next.js Environment variables](https://nextjs.org/docs/basic-features/environment-variables). When using Unleash **client-side**, with `` or `getFrontendFlags()` configure: * `NEXT_PUBLIC_UNLEASH_FRONTEND_API_URL`. URL should end with `/api/frontend` or `/proxy` * `NEXT_PUBLIC_UNLEASH_FRONTEND_API_TOKEN` [client-side API token](/concepts/api-tokens-and-client-keys#front-end-tokens) if you're using the [front-end API](/api#frontend-api). * Using [Edge](/unleash-edge) is the same as using the frontend API, so you'll need a FRONTEND\_API\_TOKEN, and your URL should end with `/api/frontend`. If using **server-side** (SSR, SSG, API), using `getDefinitions()` and `evaluateFlags()`, set: * `UNLEASH_SERVER_API_URL` of you instance. URL should end with `/api` * `UNLEASH_SERVER_API_TOKEN` [Backend API client token](/concepts/api-tokens-and-client-keys#backend-tokens) #### Detailed Explanation | Prefixable | Variable | Default | | -------------- | ---------------------------- | --------------------------------------------------------- | | `NEXT_PUBLIC_` | `UNLEASH_SERVER_API_URL` | `http://localhost:4242/api` | | `NEXT_PUBLIC_` | `UNLEASH_FRONTEND_API_URL` | `<(NEXT_PUBLIC_)UNLEASH_SERVER_API_URL>/frontend` | | **No** | `UNLEASH_SERVER_API_TOKEN` | `default:development.unleash-insecure-api-token` | | **No** | `UNLEASH_SERVER_INSTANCE_ID` | undefined | | `NEXT_PUBLIC_` | `UNLEASH_FRONTEND_API_TOKEN` | `default:development.unleash-insecure-frontend-api-token` | | `NEXT_PUBLIC_` | `UNLEASH_APP_NAME` | `nextjs` | If you plan to use configuration in the browser, add `NEXT_PUBLIC_` prefix. If both are defined and available, private variable takes priority. You can use both to have different values on client-side and server-side. Usage with GitLab's feature flags: To use this SDK with [GitLab Feature Flags](https://docs.gitlab.com/ee/operations/feature_flags.html) , use `UNLEASH_SERVER_INSTANCE_ID` instead of `UNLEASH_SERVER_API_TOKEN` to [authorize with GitLab's service](https://docs.gitlab.com/ee/operations/feature_flags.html#get-access-credentials) . ## Usage ### A). App Router This package is ready for server-side use with [App Router](https://nextjs.org/docs/app/building-your-application/routing). Refer to [`./example/README.md#App-router`](https://github.com/Unleash/unleash-nextjs-sdk/tree/main/example#app-router) for an implementation example. ```tsx import { cookies } from "next/headers"; import { evaluateFlags, flagsClient, getDefinitions } from "@unleash/nextjs"; const getFlag = async () => { const cookieStore = cookies(); const sessionId = cookieStore.get("unleash-session-id")?.value || `${Math.floor(Math.random() * 1_000_000_000)}`; const definitions = await getDefinitions({ fetchOptions: { next: { revalidate: 15 }, // Cache layer like Unleash Proxy! }, }); const { toggles } = evaluateFlags(definitions, { sessionId, }); const flags = flagsClient(toggles); return flags.isEnabled("nextjs-example"); }; export default async function Page() { const isEnabled = await getFlag(); return (

Feature flag is{" "} {isEnabled ? "ENABLED" : "DISABLED"} .

); } ``` ### B). Middleware It's possible to run this SDK in Next.js Edge Middleware. This is a great use case for A/B testing, where you can transparently redirect users to different pages based on a feature flag. Target pages can be statically generated, improving performance. Refer to [`./example/README.md#Middleware`](https://github.com/Unleash/unleash-nextjs-sdk/tree/main/example#middleware) for an implementation example. ### C). Client-side Only - Simple Use Case and for Development Purposes (CSR) Fastest way to get started is to connect frontend directly to Unleash. You can find out more about direct [Front-end API access](/api#frontend-api) in our documentation, including a guide on how to [setup a client-side SDK key](/concepts/api-tokens-and-client-keys#front-end-tokens). Important: Hooks and provider are only available in `@unleash/nextjs/client`. ```tsx import type { AppProps } from "next/app"; import { FlagProvider } from "@unleash/nextjs/client"; export default function App({ Component, pageProps }: AppProps) { return ( ); } ``` With `` in place you can now use hooks like: `useFlag`, `useVariant`, or `useFlagsStatus` to block rendering until flags are ready. ```jsx import { useFlag } from "@unleash/nextjs/client"; const YourComponent = () => { const isEnabled = useFlag("nextjs-example"); return <>{isEnabled ? "ENABLED" : "DISABLED"}; }; ``` Optionally, you can configure `FlagProvider` with the `config` prop. It will take priority over environment variables. ```jsx ", // replaces NEXT_PUBLIC_UNLEASH_FRONTEND_API_TOKEN appName: "nextjs", // replaces NEXT_PUBLIC_UNLEASH_APP_NAME refreshInterval: 15, // additional client configuration // see https://github.com/Unleash/unleash-proxy-client-js#available-options }} > ``` If you only plan to use [Unleash client-side React SDK](https://github.com/Unleash/proxy-client-react) now also works with Next.js. Check documentation there for more examples. ### D). Static Site Generation, Optimized Performance (SSG) With same access as in the client-side example above you can resolve Unleash feature flags when building static pages. ```tsx import { flagsClient, getDefinitions, evaluateFlags, getFrontendFlags, type IVariant, } from "@unleash/nextjs"; import type { GetStaticProps, NextPage } from "next"; type Data = { isEnabled: boolean; variant: IVariant; }; const ExamplePage: NextPage = ({ isEnabled, variant }) => ( <> Flag status: {isEnabled ? "ENABLED" : "DISABLED"}
Variant: {variant.name} ); export const getStaticProps: GetStaticProps = async (_ctx) => { /* Using server-side SDK: */ const definitions = await getDefinitions(); const context = {}; // optional, see https://docs.getunleash.io/concepts/unleash-context const { toggles } = evaluateFlags(definitions, context); /* Or with the proxy/front-end API */ // const { toggles } = await getFrontendFlags({ context }); const flags = flagsClient(toggles); return { props: { isEnabled: flags.isEnabled("nextjs-example"), variant: flags.getVariant("nextjs-example"), }, }; }; export default ExamplePage; ``` The same approach will work for [ISR (Incremental Static Regeneration)](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration). Both `getDefinitions()` and `getFrontendFlags()` can take arguments overriding URL, token and other request parameters. ### E). Server Side Rendering (SSR) ```tsx import { flagsClient, evaluateFlags, getDefinitions, type IVariant, } from "@unleash/nextjs"; import type { GetServerSideProps, NextPage } from "next"; type Data = { isEnabled: boolean; }; const ExamplePage: NextPage = ({ isEnabled }) => ( <>Flag status: {isEnabled ? "ENABLED" : "DISABLED"} ); export const getServerSideProps: GetServerSideProps = async (ctx) => { const sessionId = ctx.req.cookies["unleash-session-id"] || `${Math.floor(Math.random() * 1_000_000_000)}`; ctx.res.setHeader("set-cookie", `unleash-session-id=${sessionId}; path=/;`); const context = { sessionId, // needed for stickiness // userId: "123" // etc }; const definitions = await getDefinitions(); // Uses UNLEASH_SERVER_API_URL const { toggles } = evaluateFlags(definitions, context); const flags = flagsClient(toggles); // instantiates a static (non-syncing) unleash-proxy-client return { props: { isEnabled: flags.isEnabled("nextjs-example") }, }; }; export default ExamplePage; ``` ### F). Bootstrapping / Rehydration You can bootstrap Unleash React SDK to have values loaded from the start. Initial value can be customized server-side. ```tsx import App, { AppContext, type AppProps } from "next/app"; import { FlagProvider, getFrontendFlags, type IMutableContext, type IToggle, } from "@unleash/nextjs"; type Data = { toggles: IToggle[]; context: IMutableContext; }; export default function CustomApp({ Component, pageProps, toggles, context, }: AppProps & Data) { return ( ); } CustomApp.getInitialProps = async (ctx: AppContext) => { const context = { userId: "123", }; const { toggles } = await getFrontendFlags(); // use Unleash Proxy return { ...(await App.getInitialProps(ctx)), bootstrap: toggles, context, // pass context along so client can refetch correct values }; }; ``` ## Developer Toolbar The [Developer Toolbar](/integrate/toolbar) provides runtime flag and context overrides during development. It supports both client components and server-side rendering through cookie-based state sync. ### Client components Use `UnleashToolbarProvider` from `@unleash/toolbar/next` as a drop-in replacement for `FlagProvider`: ```tsx {9-20} // app/layout.tsx import { UnleashToolbarProvider } from '@unleash/toolbar/next'; import '@unleash/toolbar/toolbar.css'; export default function RootLayout({ children }) { return ( {children} ); } ``` ### Server components (SSR) The toolbar syncs state to cookies, which server components can read using `applyToolbarOverrides`: ```tsx {12} // app/server-page/page.tsx import { cookies } from 'next/headers'; import { getDefinitions, evaluateFlags, flagsClient } from '@unleash/nextjs'; import { applyToolbarOverrides } from '@unleash/toolbar/next/server'; export default async function ServerPage() { const definitions = await getDefinitions({ fetchOptions: { next: { revalidate: 15 } }, }); const cookieStore = await cookies(); const modifiedDefinitions = applyToolbarOverrides(definitions, cookieStore); const { toggles } = evaluateFlags(modifiedDefinitions, { userId: 'user-123' }); const flags = flagsClient(toggles); return
{flags.isEnabled('feature') ? 'ON' : 'OFF'}
; } ``` Refer to the [Developer Toolbar documentation](/integrate/toolbar) for configuration options and the [complete Next.js example on GitHub](https://github.com/Unleash/toolbar/tree/main/examples/nextjs). ## Server-side Flags and Metrics (New in v1.5.0) Next.js applications using Server-Side Rendering (SSR) are often deployed in serverless or short-lived environments, such as Vercel. This creates challenges for server-side metrics reporting. Typically, Unleash backend SDKs (like the [Node.js SDK](https://github.com/Unleash/unleash-client-node) run in long-lived processes, allowing them to cache metrics locally and send them to the Unleash API or Edge API at scheduled intervals. However, in some short-lived serverless environments where Next.js is commonly hosted (e.g., Vercel), there is no persistent in-memory cache across multiple requests. As a result, metrics must be reported on each request. To address this, the SDK provides a `sendMetrics` function that can be called wherever needed, but it should be executed after feature flag checks `client.isEnabled()` or variant checks `client.getVariant()`. We also recommend setting up the [Edge API](https://github.com/Unleash/unleash-edge) in front of your Unleash API. This helps protect your Unleash API from excessive traffic caused by per-request metrics reporting. ```tsx const enabled = flags.isEnabled("nextjs-example"); await flags.sendMetrics(); ``` ### No `setInterval` Support (e.g. Vercel) If your runtime does not allow `setInterval` calls then you can report metrics on each request as shown below. Consider using Unleash Edge in this scenario. #### Next.js 15 and Newer Latest versions of Next.js allow to run code after the response is sent, with [`after` function](https://nextjs.org/docs/app/api-reference/functions/after). ```ts import { after } from 'next/server' // ... export default async function Page() { // ... const flags = flagsClient(evaluated.toggles) const isEnabled = flags.isEnabled("example-flag") after(async () => { flags.sendMetrics() }) return ( // ... ) } ``` ### Next.js 14 and Older #### App Router ```tsx import {evaluateFlags, flagsClient, getDefinitions,} from "@unleash/nextjs"; export default async function Page() { const definitions = await getDefinitions({ fetchOptions: { next: { revalidate: 15 }, // Cache layer like Unleash Proxy! }, }); const context = {}; const { toggles } = evaluateFlags(definitions, context); const flags = flagsClient(toggles); const enabled = flags.isEnabled("nextjs-example"); // await client.sendMetrics().catch(() => {}); // blocking metrics flags.sendMetrics().catch(() => {}); // non-blocking metrics return <>Flag status: {enabled ? "ENABLED" : "DISABLED"} } ``` #### Page Router ```tsx import { evaluateFlags, flagsClient, getDefinitions } from "@unleash/nextjs"; import type { GetServerSideProps, NextPage } from "next"; type Data = { isEnabled: boolean; }; export const getServerSideProps: GetServerSideProps = async () => { const definitions = await getDefinitions(); const context = {}; const { toggles } = evaluateFlags(definitions, context); const flags = flagsClient(toggles); const enabled = flags.isEnabled("nextjs-example"); // await client.sendMetrics().catch(() => {}); // blocking metrics flags.sendMetrics().catch(() => {}); // non-blocking metrics return { props: { isEnabled: enabled }, }; }; const ExamplePage: NextPage = ({ isEnabled }) => ( <>Flag status: {isEnabled ? "ENABLED" : "DISABLED"} ); export default ExamplePage; ``` ## Next.js Middleware In `middleware.ts` you can use [`event.waitUntil()`](https://nextjs.org/docs/app/building-your-application/routing/middleware#waituntil-and-nextfetchevent) to reliably send metrics without delaying the response. ```tsx export async function middleware(req: NextRequest, event: NextFetchEvent) { // ... const evaluated = evaluateFlags(definitions, context); const flags = flagsClient(evaluated.toggles) const isEnabled = flags.isEnabled("example-flag") event.waitUntil(flags.sendMetrics()) // ... } ``` ## `setInterval` Support (e.g. Long-running Node Process or AWS Lambda) If your Next application resolves flags only in SSR mode and `setInterval` is supported then you may also consider using [Node.js SDK](https://github.com/Unleash/unleash-client-node) instead, which is less taxing on metrics reporting. Check [this blog post](/guides/implement-feature-flags-in-aws-lambda) for more information on short-running lambdas that still support `setInterval`. ## CLI (Experimental) You can use `unleash [action] [options]` in your `package.json` `scripts` section, or with: ```sh npx @unleash/nextjs ``` For the CLI to work, the following [environment variables](#environment-variables) must be configured with appropriate values: * `UNLEASH_SERVER_API_URL` * `UNLEASH_SERVER_API_TOKEN` The CLI will attempt to read environment values from any `.env` files if they're present. You can also set the variables directly when invoking the interface, as in the [CLI usage example](#example). ### Usage * `get-definitions ` Download feature flags definitions for bootstrapping (offline use) of server-side SDK. * `generate-types [options] ` Generate types and typed functions from feature flags defined in an Unleash instance. It will also generate strictly typed versions of `useFlag`, `useVariant`, `useFlags` and `flagsClient` (unless `--typesOnly` is used). * `-t, --typesOnly` don't include typed versions of functions exported from `@unleash/nextjs` (default: false) * `-b, --bootstrap ` load definitions from a file instead of fetching definitions - work offline * `-V` Output the version number ### Example Try it now ```sh UNLEASH_SERVER_API_URL=https://app.unleash-hosted.com/demo/api \ UNLEASH_SERVER_API_TOKEN=test-server:default.8a090f30679be7254af997864d66b86e44dcfc5291916adff72a0fb5 \ npx @unleash/nextjs generate-types ./unleash.ts ``` ## Known Limitation * When used server-side, this SDK does not support the "Hostname" and "IP" strategies. Use custom context fields and constraints instead.