Manual Setup

Learn how to set up and configure Sentry in your Next.js application, capture your first errors, logs and traces and view them in Sentry.

This guide covers manual setup for Next.js 15+ with Turbopack and App Router. For other setups, see:

You need:

Choose the features you want to configure:

How this guide works:

  1. Install - Add the Sentry SDK to your project
  2. Configure - Set up SDK initialization files and Next.js configuration
  3. Verify - Test error monitoring and any additional features you enabled

Run the command for your preferred package manager to add the Sentry SDK to your application.

Copied
npm install @sentry/nextjs --save

Extend your app's default Next.js options by adding withSentryConfig into your next.config.ts file.

next.config.ts
Copied
import type { NextConfig } from "next";
import { withSentryConfig } from "@sentry/nextjs";

const nextConfig: NextConfig = {
  // Your existing Next.js configuration
};

export default withSentryConfig(nextConfig, {
  org: "___ORG_SLUG___",
  project: "___PROJECT_SLUG___",

  // Only print logs for uploading source maps in CI
  silent: !process.env.CI,
});

Create the following files in your application's root directory (or src folder if you have one):

  • instrumentation-client.ts - Client-side SDK initialization
  • sentry.server.config.ts - Server-side SDK initialization
  • sentry.edge.config.ts - Edge runtime SDK initialization
instrumentation-client.ts
Copied
import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: "___PUBLIC_DSN___",

  // Adds request headers and IP for users
  sendDefaultPii: true,
  // ___PRODUCT_OPTION_START___ performance

  // Capture 100% in dev, 10% in production
  // Adjust based on your traffic volume
  tracesSampleRate: process.env.NODE_ENV === "development" ? 1.0 : 0.1,
  // ___PRODUCT_OPTION_END___ performance
    // ___PRODUCT_OPTION_START___ session-replay
    Sentry.replayIntegration(),
    // ___PRODUCT_OPTION_END___ session-replay
    // ___PRODUCT_OPTION_START___ user-feedback
    Sentry.feedbackIntegration({
      colorScheme: "system",
    }),
    // ___PRODUCT_OPTION_END___ user-feedback
  // ___PRODUCT_OPTION_START___ session-replay

  // Capture Replay for 10% of all sessions,
  // plus for 100% of sessions with an error
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  // ___PRODUCT_OPTION_END___ session-replay
  // ___PRODUCT_OPTION_START___ logs

  // Enable logs to be sent to Sentry
  enableLogs: true,
  // ___PRODUCT_OPTION_END___ logs
});

// ___PRODUCT_OPTION_START___ performance
// This export will instrument router navigations
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
// ___PRODUCT_OPTION_END___ performance

Create a Next.js Instrumentation file named instrumentation.ts in your project root (or src folder). This file imports your server and edge configurations and exports onRequestError to capture server-side errors.

instrumentation.ts
Copied
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");
  }
}

// Capture errors from Server Components, middleware, and proxies
export const onRequestError = Sentry.captureRequestError;

Create app/global-error.tsx to capture errors that occur anywhere in your App Router application.

global-error.tsx
Copied
"use client";

import * as Sentry from "@sentry/nextjs";
import NextError from "next/error";
import { useEffect } from "react";

export default function GlobalError({
  error,
}: {
  error: Error & { digest?: string };
}) {
  useEffect(() => {
    Sentry.captureException(error);
  }, [error]);

  return (
    <html>
      <body>
        {/* `NextError` is the default Next.js error page component. Its type
        definition requires a `statusCode` prop. However, since the App Router
        does not expose status codes for errors, we simply pass 0 to render a
        generic error message. */}
        <NextError statusCode={0} />
      </body>
    </html>
  );
}

Wrap your Server Actions with Sentry.withServerActionInstrumentation().

app/actions.ts
Copied
"use server";
import * as Sentry from "@sentry/nextjs";
import { headers } from "next/headers";

export async function submitForm(formData: FormData) {
  return Sentry.withServerActionInstrumentation(
    "submitForm", // Action name for Sentry
    {
      headers: await headers(), // Connect client and server traces
      formData, // Attach form data to events
      recordResponse: true, // Include response data
    },
    async () => {
      // Your server action logic
      const result = await processForm(formData);
      return { success: true, data: result };
    },
  );
}

Add the authToken option to your next.config.ts to enable readable stack traces. Set the SENTRY_AUTH_TOKEN environment variable in your CI/CD.

next.config.ts
Copied
export default withSentryConfig(nextConfig, {
  org: "___ORG_SLUG___",
  project: "___PROJECT_SLUG___",

  // Pass the auth token
  authToken: process.env.SENTRY_AUTH_TOKEN,

  // Upload a larger set of source maps for prettier stack traces
  widenClientFileUpload: true,
});

Prevent ad blockers from blocking Sentry events by routing them through your Next.js server.

Using Next.js middleware with tunneling

If you're using Next.js middleware (middleware.ts) that intercepts requests, exclude the tunnel route:

middleware.ts
Copied
export const config = {
  matcher: ["/((?!monitoring|_next/static|_next/image|favicon.ico).*)"],
};
next.config.ts
Copied
export default withSentryConfig(nextConfig, {
  // Use a fixed route (recommended)
  tunnelRoute: "/monitoring",
});

Test your error monitoring setup by throwing an error and viewing it in Sentry.

Add this button to any page and click it to trigger a test error.

Copied
<button
  type="button"
  onClick={() => {
    throw new Error("Sentry Test Error");
  }}
>
  Break the world
</button>;

Open Issues in Sentry to see your test error. Learn more about capturing errors.

Based on the features you selected above, verify each one is working correctly.

Session Replay captures video-like reproductions of user sessions. It's configured with replayIntegration() in your client config.

By default, Sentry masks all text, inputs, and media. You can customize this in Privacy Configuration.

Verify: Trigger an error or navigate your app, then check Replays in Sentry.

instrumentation-client.ts
Copied
Sentry.init({
  dsn: "___PUBLIC_DSN___",

  integrations: [
    Sentry.replayIntegration({
      maskAllText: true,
      maskAllInputs: true,
      blockAllMedia: true,
    }),
  ],

  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
});

Tracing is configured with tracesSampleRate in your SDK init files. Next.js routes and API calls are automatically instrumented.

Add custom spans to trace specific operations in your code.

Verify: Navigate to any page, then check Traces in Sentry.

Copied
import * as Sentry from "@sentry/nextjs";

// Wrap operations with spans
const result = await Sentry.startSpan(
  { name: "expensive-operation", op: "function" },
  async () => {
    return await fetchDataFromAPI();
  },
);

Logs are enabled with enableLogs: true in your SDK config. Use the Sentry logger to send structured logs from anywhere in your application.

Connect popular logging libraries via Integrations.

Verify: Add a log statement, trigger it, then check Logs in Sentry.

Copied
import * as Sentry from "@sentry/nextjs";

Sentry.logger.info("User clicked checkout button");

Sentry.logger.info("Order completed", {
  orderId: "12345",
  total: 99.99,
});

Sentry.logger.warn("Warning message");
Sentry.logger.error("Error occurred");

User Feedback adds an embeddable widget via feedbackIntegration() that lets users report bugs directly from your app.

Verify: Look for the feedback button (bottom-right corner), submit test feedback, then check User Feedback in Sentry.

Learn more about User Feedback

instrumentation-client.ts
Copied
Sentry.init({
  dsn: "___PUBLIC_DSN___",

  integrations: [
    Sentry.feedbackIntegration({
      colorScheme: "system",
    }),
  ],
});

Hybrid Apps (App Router + Pages Router)

If your application uses both the App Router and Pages Router:

  1. Follow this guide for App Router components
  2. Add a pages/_error.tsx file for Pages Router error handling (see Pages Router Setup)
  3. Both routers share the same Sentry configuration files

Next Steps

You've successfully integrated Sentry into your Next.js application! Here's what to explore next:

Are you having problems setting up the SDK?
Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").