# Sentry Next.js: three runtimes, three init files, one wrapped config

## Use the wizard

```
npx @sentry/wizard@latest -i nextjs
```

It creates separate init files because Next.js runs your code in three environments:

- Client: `instrumentation-client.ts` (browser)
- Server: `sentry.server.config.ts` (Node.js)
- Edge: `sentry.edge.config.ts` (edge runtime)

And `instrumentation.ts` registers them:

```ts
import * as Sentry from "@sentry/nextjs";

export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    await import("./sentry.server.config");
  }
  if (process.env.NEXT_RUNTIME === "edge") {
    await import("./sentry.edge.config");
  }
}

export const onRequestError = Sentry.captureRequestError;
```

## The wrapped next.config

```ts
import { withSentryConfig } from "@sentry/nextjs/config";

export default withSentryConfig(nextConfig, {
  org: "[your org slug]",
  project: "[your project slug]",
  authToken value process.env.SENTRY_AUTH_TOKEN, // secret, CI only, never client-exposed
  tunnelRoute: "/sentry-tunnel", // routes events through your server, dodges adblockers
  silent: !process.env.CI,
});
```

`org` and `project` here are for build-time source map uploads, which is why they sit next to the auth token. This is also where the classic mixup happens: the DSN goes in the three init files, the AUTH TOKEN goes here. Swapping them breaks both.

## Sample rates per environment

The wizard generates `tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1`. Keep that shape. Setting 1.0 unconditionally is the fastest way to burn a month of span quota in a week.

## Don't forget global-error.tsx

The wizard adds `app/global-error.tsx` to catch React rendering errors in App Router. If you hand-rolled the setup and rendering crashes are missing from Sentry, that file is what you forgot.