--- name: sentry-react-sdk description: Full Sentry SDK setup for React. Use when asked to "add Sentry to React", "install @sentry/react", or configure error monitoring, tracing, session replay, profiling, or logging for React applications. Supports React 16+, React Router v5-v7, TanStack Router, Redux, Vite, and webpack. license: Apache-2.0 --- # Sentry React SDK Opinionated wizard that scans your React project and guides you through complete Sentry setup. ## Invoke This Skill When - User asks to "add Sentry to React" or "set up Sentry" in a React app - User wants error monitoring, tracing, session replay, profiling, or logging in React - User mentions `@sentry/react`, React Sentry SDK, or Sentry error boundaries - User wants to monitor React Router navigation, Redux state, or component performance > **Note:** SDK versions and APIs below reflect current Sentry docs at time of writing (`@sentry/react` ≥8.0.0). > Always verify against [docs.sentry.io/platforms/javascript/guides/react/](https://docs.sentry.io/platforms/javascript/guides/react/) before implementing. --- ## Phase 1: Detect Run these commands to understand the project before making any recommendations: ```bash # Detect React version cat package.json | grep -E '"react"|"react-dom"' # Check for existing Sentry cat package.json | grep '"@sentry/' # Detect router cat package.json | grep -E '"react-router-dom"|"@tanstack/react-router"' # Detect state management cat package.json | grep -E '"redux"|"@reduxjs/toolkit"' # Detect build tool ls vite.config.ts vite.config.js webpack.config.js craco.config.js 2>/dev/null cat package.json | grep -E '"vite"|"react-scripts"|"webpack"' # Detect logging libraries cat package.json | grep -E '"pino"|"winston"|"loglevel"' # Check for companion backend in adjacent directories ls ../backend ../server ../api 2>/dev/null cat ../go.mod ../requirements.txt ../Gemfile ../pom.xml 2>/dev/null | head -3 ``` **What to determine:** | Question | Impact | |----------|--------| | React 19+? | Use `reactErrorHandler()` hook pattern | | React <19? | Use `Sentry.ErrorBoundary` | | `@sentry/react` already present? | Skip install, go straight to feature config | | `react-router-dom` v5 / v6 / v7? | Determines which router integration to use | | `@tanstack/react-router`? | Use `tanstackRouterBrowserTracingIntegration()` | | Redux in use? | Recommend `createReduxEnhancer()` | | Vite detected? | Source maps via `sentryVitePlugin` | | CRA (`react-scripts`)? | Source maps via `@sentry/webpack-plugin` in CRACO | | Backend directory found? | Trigger Phase 4 cross-link suggestion | --- ## Phase 2: Recommend Present a concrete recommendation based on what you found. Don't ask open-ended questions — lead with a proposal: **Recommended (core coverage):** - ✅ **Error Monitoring** — always; captures unhandled errors, React error boundaries, React 19 hooks - ✅ **Tracing** — React SPAs benefit from page load, navigation, and API call tracing - ✅ **Session Replay** — recommended for user-facing apps; records sessions around errors **Optional (enhanced observability):** - ⚡ **Logging** — structured logs via `Sentry.logger.*`; recommend when structured log search is needed - ⚡ **Profiling** — JS Self-Profiling API (⚠️ experimental; requires cross-origin isolation headers) **Recommendation logic:** | Feature | Recommend when... | |---------|------------------| | Error Monitoring | **Always** — non-negotiable baseline | | Tracing | **Always for React SPAs** — page load + navigation spans are high-value | | Session Replay | User-facing app, login flows, or checkout pages | | Logging | App needs structured log search or log-to-trace correlation | | Profiling | Performance-critical app; server sends `Document-Policy: js-profiling` header | **React-specific extras:** - React 19 detected → set up `reactErrorHandler()` on `createRoot` - React Router detected → configure matching router integration (see Phase 3) - Redux detected → add `createReduxEnhancer()` to Redux store - Vite detected → configure `sentryVitePlugin` for source maps (essential for readable stack traces) Propose: *"I recommend setting up Error Monitoring + Tracing + Session Replay. Want me to also add Logging or Profiling?"* --- ## Phase 3: Guide ### Install ```bash npm install @sentry/react --save ``` ### Create `src/instrument.ts` Sentry must initialize **before any other code runs**. Put `Sentry.init()` in a dedicated sidecar file: ```typescript import * as Sentry from "@sentry/react"; Sentry.init({ dsn: import.meta.env.VITE_SENTRY_DSN, // Adjust per build tool (see table below) environment: import.meta.env.MODE, release: import.meta.env.VITE_APP_VERSION, // inject at build time sendDefaultPii: true, integrations: [ Sentry.browserTracingIntegration(), Sentry.replayIntegration({ maskAllText: true, blockAllMedia: true, }), ], // Tracing tracesSampleRate: 1.0, // lower to 0.1–0.2 in production tracePropagationTargets: ["localhost", /^https:\/\/yourapi\.io/], // Session Replay replaysSessionSampleRate: 0.1, replaysOnErrorSampleRate: 1.0, enableLogs: true, }); ``` **DSN environment variable by build tool:** | Build Tool | Variable Name | Access in code | |------------|--------------|----------------| | Vite | `VITE_SENTRY_DSN` | `import.meta.env.VITE_SENTRY_DSN` | | Create React App | `REACT_APP_SENTRY_DSN` | `process.env.REACT_APP_SENTRY_DSN` | | Custom webpack | `SENTRY_DSN` | `process.env.SENTRY_DSN` | ### Entry Point Setup Import `instrument.ts` as the **very first import** in your entry file: ```tsx // src/main.tsx (Vite) or src/index.tsx (CRA/webpack) import "./instrument"; // ← MUST be first import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; createRoot(document.getElementById("root")!).render( ); ``` ### React Version-Specific Error Handling **React 19+** — use `reactErrorHandler()` on `createRoot`: ```tsx import { reactErrorHandler } from "@sentry/react"; createRoot(document.getElementById("root")!, { onUncaughtError: reactErrorHandler(), onCaughtError: reactErrorHandler(), onRecoverableError: reactErrorHandler(), }).render(); ``` **React <19** — wrap your app in `Sentry.ErrorBoundary`: ```tsx import * as Sentry from "@sentry/react"; createRoot(document.getElementById("root")!).render( Something went wrong

} showDialog>
); ``` Use `` for any sub-tree that should catch errors independently (route sections, widgets, etc.). ### Router Integration Configure the matching integration for your router: | Router | Integration | Notes | |--------|------------|-------| | React Router v7 | `reactRouterV7BrowserTracingIntegration` | `useEffect`, `useLocation`, `useNavigationType`, `createRoutesFromChildren`, `matchRoutes` from `react-router` | | React Router v6 | `reactRouterV6BrowserTracingIntegration` | `useEffect`, `useLocation`, `useNavigationType`, `createRoutesFromChildren`, `matchRoutes` from `react-router-dom` | | React Router v5 | `reactRouterV5BrowserTracingIntegration` | Wrap routes in `withSentryRouting(Route)` | | TanStack Router | `tanstackRouterBrowserTracingIntegration(router)` | Pass router instance — no hooks required | | No router / custom | `browserTracingIntegration()` | Names transactions by URL path | **React Router v6/v7 setup:** ```typescript // in instrument.ts integrations array: import React from "react"; import { createRoutesFromChildren, matchRoutes, useLocation, useNavigationType, } from "react-router-dom"; // or "react-router" for v7 import * as Sentry from "@sentry/react"; import { reactRouterV6BrowserTracingIntegration } from "@sentry/react"; import { createBrowserRouter } from "react-router-dom"; // Option A — createBrowserRouter (recommended for v6.4+): const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV6(createBrowserRouter); const router = sentryCreateBrowserRouter([...routes]); // Option B — createBrowserRouter for React Router v7: // const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV7(createBrowserRouter); // Option C — integration with hooks (v6 without data APIs): Sentry.init({ integrations: [ reactRouterV6BrowserTracingIntegration({ useEffect: React.useEffect, useLocation, useNavigationType, matchRoutes, createRoutesFromChildren, }), ], }); ``` **TanStack Router setup:** ```typescript import { tanstackRouterBrowserTracingIntegration } from "@sentry/react"; // Pass your TanStack router instance: Sentry.init({ integrations: [tanstackRouterBrowserTracingIntegration(router)], }); ``` ### Redux Integration (when detected) ```typescript import * as Sentry from "@sentry/react"; import { configureStore } from "@reduxjs/toolkit"; const store = configureStore({ reducer: rootReducer, enhancers: (getDefaultEnhancers) => getDefaultEnhancers().concat(Sentry.createReduxEnhancer()), }); ``` ### Source Maps Setup (strongly recommended) Without source maps, stack traces show minified code. Set up the build plugin to upload source maps automatically: **Vite (`vite.config.ts`):** ```typescript import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import { sentryVitePlugin } from "@sentry/vite-plugin"; export default defineConfig({ build: { sourcemap: "hidden" }, plugins: [ react(), sentryVitePlugin({ org: process.env.SENTRY_ORG, project: process.env.SENTRY_PROJECT, authToken: process.env.SENTRY_AUTH_TOKEN, }), ], }); ``` Add to `.env` (never commit): ```bash SENTRY_AUTH_TOKEN=sntrys_... SENTRY_ORG=my-org-slug SENTRY_PROJECT=my-project-slug ``` **Create React App (via CRACO):** ```bash npm install @craco/craco @sentry/webpack-plugin --save-dev ``` ```javascript // craco.config.js const { sentryWebpackPlugin } = require("@sentry/webpack-plugin"); module.exports = { webpack: { plugins: { add: [ sentryWebpackPlugin({ org: process.env.SENTRY_ORG, project: process.env.SENTRY_PROJECT, authToken: process.env.SENTRY_AUTH_TOKEN, }), ], }, }, }; ``` ### For Each Agreed Feature Walk through features one at a time. Load the reference file, follow its steps, verify before moving on: | Feature | Reference | Load when... | |---------|-----------|-------------| | Error Monitoring | `${SKILL_ROOT}/references/error-monitoring.md` | Always (baseline) | | Tracing | `${SKILL_ROOT}/references/tracing.md` | SPA navigation / API call tracing | | Session Replay | `${SKILL_ROOT}/references/session-replay.md` | User-facing app | | Logging | `${SKILL_ROOT}/references/logging.md` | Structured log search / log-to-trace | | Profiling | `${SKILL_ROOT}/references/profiling.md` | Performance-critical app | | React Features | `${SKILL_ROOT}/references/react-features.md` | Redux, component tracking, source maps, integrations catalog | For each feature: `Read ${SKILL_ROOT}/references/.md`, follow steps exactly, verify it works. --- ## Configuration Reference ### Key `Sentry.init()` Options | Option | Type | Default | Notes | |--------|------|---------|-------| | `dsn` | `string` | — | **Required.** SDK disabled when empty | | `environment` | `string` | `"production"` | e.g., `"staging"`, `"development"` | | `release` | `string` | — | e.g., `"my-app@1.0.0"` or git SHA — links errors to releases | | `sendDefaultPii` | `boolean` | `false` | Includes IP addresses and request headers | | `tracesSampleRate` | `number` | — | 0–1; `1.0` in dev, `0.1–0.2` in prod | | `tracesSampler` | `function` | — | Per-transaction sampling; overrides rate | | `tracePropagationTargets` | `(string\|RegExp)[]` | — | Outgoing URLs that receive distributed tracing headers | | `replaysSessionSampleRate` | `number` | — | Fraction of all sessions recorded | | `replaysOnErrorSampleRate` | `number` | — | Fraction of error sessions recorded | | `enableLogs` | `boolean` | `false` | Enable `Sentry.logger.*` API | | `attachStacktrace` | `boolean` | `false` | Stack traces on `captureMessage()` calls | | `maxBreadcrumbs` | `number` | `100` | Breadcrumbs stored per event | | `debug` | `boolean` | `false` | Verbose SDK output to console | | `tunnel` | `string` | — | Proxy URL to bypass ad blockers | ### React Compatibility Matrix | React Version | Error handling approach | SDK minimum | |---------------|------------------------|-------------| | React 19+ | `reactErrorHandler()` on `createRoot` | `@sentry/react` ≥8.0.0 | | React 16–18 | `Sentry.ErrorBoundary` component | `@sentry/react` ≥7.0.0 | | React 16 | `componentDidCatch` class boundaries | `@sentry/react` ≥6.0.0 | --- ## Verification Trigger test events to confirm Sentry is receiving data: ```tsx // Add a temporary test button anywhere in your app import * as Sentry from "@sentry/react"; function SentryTest() { return ( <> ); } ``` Check the Sentry dashboard: - **Issues** → error appears within seconds - **Traces** → page load and navigation transactions visible - **Replays** → session recording visible after page interaction - **Logs** → structured log entries if logging enabled Set `debug: true` in `Sentry.init()` and check the browser console if nothing appears. --- ## Phase 4: Cross-Link After completing React setup, check for a companion backend missing Sentry coverage: ```bash ls ../backend ../server ../api ../go ../python 2>/dev/null cat ../go.mod 2>/dev/null | head -3 cat ../requirements.txt ../pyproject.toml 2>/dev/null | head -3 cat ../Gemfile 2>/dev/null | head -3 cat ../pom.xml 2>/dev/null | grep '' | head -3 ``` If a backend exists without Sentry configured, suggest the matching skill: | Backend detected | Suggest skill | |-----------------|--------------| | Go (`go.mod`) | `sentry-go-sdk` | | Python (`requirements.txt`, `pyproject.toml`) | `sentry-python-sdk` | | Ruby (`Gemfile`) | `sentry-ruby-sdk` | | Java (`pom.xml`, `build.gradle`) | Use `@sentry/java` — see [docs.sentry.io/platforms/java/](https://docs.sentry.io/platforms/java/) | | Node.js (Express, Fastify) | Use `@sentry/node` — see [docs.sentry.io/platforms/javascript/guides/express/](https://docs.sentry.io/platforms/javascript/guides/express/) | --- ## Troubleshooting | Issue | Solution | |-------|----------| | Events not appearing | Set `debug: true`, check DSN, open browser console for SDK errors | | Source maps not working | Build in production mode (`npm run build`); verify `SENTRY_AUTH_TOKEN` is set | | Minified stack traces | Source maps not uploading — check plugin config and auth token | | `instrument.ts` not running first | Verify it's the first import in entry file before React/app imports | | React 19 errors not captured | Confirm `reactErrorHandler()` is passed to all three `createRoot` options | | React <19 errors not captured | Ensure `` wraps the component tree | | Router transactions named `` | Add router integration matching your router version | | `tracePropagationTargets` not matching | Check regex escaping; default is `localhost` and your DSN origin only | | Session replay not recording | Confirm `replayIntegration()` is in init; check `replaysSessionSampleRate` | | Redux actions not in breadcrumbs | Add `Sentry.createReduxEnhancer()` to store enhancers | | Ad blockers dropping events | Set `tunnel: "/sentry-tunnel"` and add server-side relay endpoint | | High replay storage costs | Lower `replaysSessionSampleRate`; keep `replaysOnErrorSampleRate: 1.0` | | Profiling not working | Verify `Document-Policy: js-profiling` header is set on document responses |