# Next.js SDK

> Add Whisperr to a Next.js App Router app with @whisperr/next: a provider for the root layout and useWhisperr() in client components.

`@whisperr/next` adds Whisperr to a Next.js App Router app. It re-exports `WhisperrProvider` and `useWhisperr()` from [`@whisperr/react`](/sdks/react/) behind a `"use client"` boundary, so you can put the provider in a server component layout. All behavior comes from [`@whisperr/web`](/sdks/web/).

## Install

```bash
npm i @whisperr/next @whisperr/web
```

The packages are [`@whisperr/next`](https://www.npmjs.com/package/@whisperr/next) and [`@whisperr/web`](https://www.npmjs.com/package/@whisperr/web) on npm. They release together; the current version is 0.4.0.

## Add the provider to the root layout

`app/layout.tsx`

```tsx
import { WhisperrProvider } from "@whisperr/next";


const key = process.env.NEXT_PUBLIC_WHISPERR_KEY;


export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {/* Without a key (a preview or CI build), the SDK stays off instead of throwing. */}
        <WhisperrProvider options={{ apiKey: key ?? "", disabled: !key }}>
          {children}
        </WhisperrProvider>
      </body>
    </html>
  );
}
```

`.env.local`

```dotenv
NEXT_PUBLIC_WHISPERR_KEY=wpk_your_publishable_key
```

A `NEXT_PUBLIC_` variable ships in the browser bundle, so it must hold the publishable key (`wpk_…`), shown as an **App** key in **Settings → API keys**. Never put the server key (`wrk_…`) in a `NEXT_PUBLIC_` variable.

## Track events in client components

`app/documents/share-button.tsx`

```tsx
"use client";
import { useWhisperr } from "@whisperr/next";


export function ShareButton({ share }: { share: () => Promise<void> }) {
  const whisperr = useWhisperr();
  // Track after the action succeeds. "document_shared" is an example name.
  async function onClick() {
    await share();
    whisperr.track("document_shared");
  }
  return <button onClick={onClick}>Share</button>;
}
```

`useWhisperr()` returns the full Web SDK client: `identify()`, `track()`, `setAppLanguage()`, `reset()` and the rest. See [Web SDK methods](/sdks/web/#methods). Call `identify()` in a client component after sign-in and when you restore a session.

## How do I pass an onError callback in Next.js?

A server component cannot pass a function to a client component. To use `onError`, or any option you build in code, wrap the provider in your own client component:

`app/whisperr-provider.tsx`

```tsx
"use client";
import { WhisperrProvider } from "@whisperr/next";


export function AppWhisperrProvider({ children }: { children: React.ReactNode }) {
  return (
    <WhisperrProvider
      options={{
        apiKey: process.env.NEXT_PUBLIC_WHISPERR_KEY!,
        onError: (error) => console.warn("whisperr", error.type, error.message),
      }}
    >
      {children}
    </WhisperrProvider>
  );
}
```

Then render `<AppWhisperrProvider>` in `app/layout.tsx`.

## Track server-side events

For route handlers, server actions and webhooks, use [`@whisperr/node`](/sdks/node/) with the server key. Pass the same user id you pass to `identify()` in the browser, and both sources land on [one timeline](/concepts/events/#one-user-one-timeline).

## Common questions

### Do I need to track Next.js route changes myself?

No. The Web SDK captures page_viewed on load and on every History API navigation, which covers Next.js client-side navigation.

### Can I call useWhisperr() in a server component?

No. useWhisperr() is a React hook, so call it in a client component. For server-side events, use @whisperr/node with the server key.

### Why must the Next.js key be a publishable key?

A NEXT_PUBLIC_ variable is built into the browser bundle, where anyone can read it. The publishable key (wpk_…) is made for that. The server key (wrk_…) must stay on your server.

Source: https://docs.whisperr.net/sdks/next/
