Manual Setup | Sentry for Next.js
Source URL: https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup
Manual Setup | Sentry for Next.js
Section titled “Manual Setup | Sentry for Next.js”For the fastest setup, we recommend using the wizard installer.
This guide covers manual setup for Next.js 15+ with Turbopack and App Router. For other setups, see:
- Pages Router Setup - For applications using the Pages Router
- Webpack Setup - For applications not using Turbopack
You need:
Choose the features you want to configure:
Error Monitoring[x]Logs[ ]Session Replay[x]Tracing[ ]User Feedback
How this guide works:
- Install - Add the Sentry SDK to your project
- Configure - Set up SDK initialization files and Next.js configuration
- 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.
npm install @sentry/nextjs --saveExtend your app’s default Next.js options by adding withSentryConfig into your next.config.ts file.
next.config.ts
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 initializationsentry.server.config.ts- Server-side SDK initializationsentry.edge.config.ts- Edge runtime SDK initialization
Include your DSN directly in these files, or use a public environment variable like NEXT_PUBLIC_SENTRY_DSN.
instrumentation-client.ts
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 integrations: [ // ___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 navigationsexport const onRouterTransitionStart = Sentry.captureRouterTransitionStart;// ___PRODUCT_OPTION_END___ performanceAdjust sample rates for production
Section titled “Adjust sample rates for production”The example above samples 100% of traces in development and 10% in production. Monitor your usage stats and adjust tracesSampleRate based on your traffic volume. Learn more about sampling configuration.
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.
The onRequestError hook requires @sentry/nextjs version 8.28.0 or higher and Next.js 15.
instrumentation.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"); }}
// Capture errors from Server Components, middleware, and proxiesexport const onRequestError = Sentry.captureRequestError;Create app/global-error.tsx to capture errors that occur anywhere in your App Router application.
global-error.tsx
"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
"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.
Important
Section titled “Important”Keep your auth token secret and out of version control.
next.config.ts
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.
This increases server load. Consider the trade-off for your application.
Using Next.js middleware with tunneling
If you’re using Next.js middleware (middleware.ts) that intercepts requests, exclude the tunnel route:
middleware.ts
export const config = { matcher: ["/((?!monitoring|_next/static|_next/image|favicon.ico).*)"],};next.config.ts
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.
Important
Section titled “Important”Errors triggered from within your browser’s developer tools (like the browser console) are sandboxed, so they will not trigger Sentry’s error monitoring.
<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
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.
import * as Sentry from "@sentry/nextjs";
// Wrap operations with spansconst 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.
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
Sentry.init({ dsn: "___PUBLIC_DSN___",
integrations: [ Sentry.feedbackIntegration({ colorScheme: "system", }), ],});Hybrid Apps (App Router + Pages Router)
Section titled “Hybrid Apps (App Router + Pages Router)”If your application uses both the App Router and Pages Router:
- Follow this guide for App Router components
- Add a
pages/_error.tsxfile for Pages Router error handling (see Pages Router Setup) - Both routers share the same Sentry configuration files
The Sentry SDK automatically detects which router is being used and applies the appropriate instrumentation.
Next Steps
Section titled “Next Steps”You’ve successfully integrated Sentry into your Next.js application! Here’s what to explore next:
- Logs Integrations - Connect popular logging libraries like Pino, Winston, and Bunyan
- Distributed Tracing - Trace requests across services and microservices
- AI Agent Monitoring - Monitor AI agents built with Vercel AI SDK, LangChain, and more
- Connect GitHub + Seer - Enable AI-powered root cause analysis by connecting your GitHub repository
- Configuration Options - Explore extended SDK configuration options
Are you having problems setting up the SDK?
- Try the installation wizard for automatic setup
- Get support