Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Full Sentry SDK setup for React Router Framework mode. Use when asked to \"add Sentry to React Router Framework\", \"install @sentry/react-router\", or configure error monitoring, tracing, profiling, session replay, logs, or user feedback for a React Router v7 framework app.
.claude/skills/kunanonj-cursor-plugin-sentry-sentry-react-router-framework-sdk/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 142% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 602% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 75% | 0% |
> All Skills > SDK Setup > React Router Framework SDK
Opinionated wizard that scans your React Router Framework project and guides you through complete Sentry setup across client and server entry points.
@sentry/react-routerentry.client.tsx, entry.server.tsx) and wants tracing/error capturereactRouterTracingIntegration, sentryOnError, createSentryHandleRequest, or React Router wizard setup> Important: This SDK is currently beta. > For React Router non-framework/data/declarative mode (v5/v6/v7), use sentry-react-sdk with @sentry/react integrations instead.
Run these commands to understand the project before making any recommendations:
bash# Detect React Router Framework indicators and versions cat package.json | grep -E '"react-router"|"@react-router/"|"react-router-dev"|"react-router-serve"' # Detect Sentry package choice cat package.json | grep -E '"@sentry/react-router"|"@sentry/react"|"@sentry/profiling-node"' # Check entry point visibility and server instrumentation files ls entry.client.tsx entry.server.tsx instrument.server.mjs react-router.config.ts vite.config.ts 2>/dev/null # Check if React Router files are still hidden (framework mode helper command available) cat package.json | grep -E '"reveal"|react-router' # Detect runtime startup scripts and import strategy cat package.json | grep -E '"dev"|"start"|NODE_OPTIONS|--import' # Detect optional logging/profile-related dependencies cat package.json | grep -E '"pino"|"winston"|"@sentry/profiling-node"' # Detect companion backend 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 | |----------|--------| | @sentry/react-router already installed? | Skip install and move to feature setup | | Framework entry files exposed? | Need npx react-router reveal before manual config | | Using @sentry/react instead? | This is likely non-framework routing; redirect to sentry-react-sdk | | react-router.config.ts + Vite config present? | Source map upload and build-end hook setup path | | NODE_OPTIONS --import available? | Preferred server instrumentation startup path | | @sentry/profiling-node desired/available? | Enable server profiling integration | | Backend directory found? | Trigger Phase 4 cross-link suggestion |
Present a concrete recommendation based on what you found. Do not ask open-ended questions — lead with a proposal:
Recommended (core coverage):
Optional (enhanced observability):
@sentry/profiling-nodeSentry.logger.* ingestion and correlationRecommendation logic:
| Feature | Recommend when... | |---------|------------------| | Error Monitoring | Always — non-negotiable baseline | | Tracing | Usually yes in framework apps; route and request timing is high-value | | Session Replay | User-facing product or difficult UX debugging | | Profiling | Server performance investigations needed; Node runtime compatibility verified | | Logs | Team wants log-search and trace correlation in Sentry | | User Feedback | Product/support teams need direct in-app issue reports |
Propose: "I recommend Error Monitoring + Tracing + Session Replay first. Want me to also enable Profiling, Logs, and User Feedback?"
> You need to run this yourself — the wizard is interactive and may require browser login: > > bash > npx @sentry/wizard@latest -i reactRouter > > > It installs @sentry/react-router, exposes React Router entry files, creates instrumentation files, updates root error handling, configures source map upload, and adds verification examples. > > Once it finishes, continue at Verification.
If the user skips wizard setup, continue with manual setup below.
bashnpm install @sentry/react-router --save
If profiling is needed:
bashnpm install @sentry/profiling-node --save
bashnpx react-router reveal
entry.client.tsxtsximport * as Sentry from "@sentry/react-router"; import { startTransition, StrictMode } from "react"; import { hydrateRoot } from "react-dom/client"; import { HydratedRouter } from "react-router/dom"; Sentry.init({ dsn: "___PUBLIC_DSN___", sendDefaultPii: true, integrations: [ Sentry.reactRouterTracingIntegration(), Sentry.replayIntegration(), Sentry.feedbackIntegration({ colorScheme: "system" }), ], enableLogs: true, tracesSampleRate: 1.0, tracePropagationTargets: [/^\//, /^https:\/\/yourserver\.io\/api/], replaysSessionSampleRate: 0.1, replaysOnErrorSampleRate: 1.0, }); startTransition(() => { hydrateRoot( document, <StrictMode> <HydratedRouter onError={Sentry.sentryOnError} /> </StrictMode>, ); });
instrument.server.mjsjavascriptimport * as Sentry from "@sentry/react-router"; import { nodeProfilingIntegration } from "@sentry/profiling-node"; Sentry.init({ dsn: "___PUBLIC_DSN___", sendDefaultPii: true, enableLogs: true, integrations: [nodeProfilingIntegration()], tracesSampleRate: 1.0, profileSessionSampleRate: 1.0, });
entry.server.tsxtsximport * as Sentry from "@sentry/react-router"; import { createReadableStreamFromReadable } from "@react-router/node"; import { renderToPipeableStream } from "react-dom/server"; import { ServerRouter } from "react-router"; const handleRequest = Sentry.createSentryHandleRequest({ ServerRouter, renderToPipeableStream, createReadableStreamFromReadable, }); export default handleRequest; export const handleError = Sentry.createSentryHandleError({ logErrors: false, });
For custom server logic, use wrapSentryHandleRequest, getMetaTagTransformer, and manual Sentry.captureException in your custom handleError.
Prefer NODE_OPTIONS --import:
json{ "scripts": { "dev": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router dev", "start": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router-serve ./build/server/index.js" } }
Fallback for platforms where runtime flags are restricted:
tsximport "./instrument.server.mjs";
This direct-import method can result in incomplete auto-instrumentation compared to --import.
vite.config.ts:
typescriptimport { reactRouter } from "@react-router/dev/vite"; import { sentryReactRouter, type SentryReactRouterBuildOptions, } from "@sentry/react-router"; import { defineConfig } from "vite"; const sentryConfig: SentryReactRouterBuildOptions = { org: "___ORG_SLUG___", project: "___PROJECT_SLUG___", authToken: process.env.SENTRY_AUTH_TOKEN, }; export default defineConfig((config) => { return { plugins: [reactRouter(), sentryReactRouter(sentryConfig, config)], }; });
react-router.config.ts:
typescriptimport type { Config } from "@react-router/dev/config"; import { sentryOnBuildEnd } from "@sentry/react-router"; export default { ssr: true, buildEnd: async ({ viteConfig, reactRouterConfig, buildManifest }) => { await sentryOnBuildEnd({ viteConfig, reactRouterConfig, buildManifest }); }, } satisfies Config;
Walk through features one at a time. Load the reference file, follow steps exactly, and verify before moving on:
| Feature | Reference | Load when... | |---------|-----------|-------------| | Error Monitoring | ${SKILL_ROOT}/references/error-monitoring.md | Always | | Tracing | ${SKILL_ROOT}/references/tracing.md | Route/request performance visibility needed | | Profiling | ${SKILL_ROOT}/references/profiling.md | Server performance analysis needed | | Session Replay | ${SKILL_ROOT}/references/session-replay.md | User-facing app | | Logs | ${SKILL_ROOT}/references/logging.md | Structured logs/correlation needed | | User Feedback | ${SKILL_ROOT}/references/user-feedback.md | In-app feedback flows needed | | Framework Features | ${SKILL_ROOT}/references/react-router-framework-features.md | Entry files, wrappers, source maps, startup import strategy |
For each feature: Read ${SKILL_ROOT}/references/<feature>.md, follow steps exactly, verify it works.
Sentry.init() options| Option | Type | Default | Notes | |--------|------|---------|-------| | dsn | string | — | Required; SDK disabled when empty | | sendDefaultPii | boolean | false | Includes headers/IP-derived user context | | integrations | Integration[] | SDK defaults | Add tracing/replay/feedback/profiling integrations | | enableLogs | boolean | false | Enables Sentry.logger.* ingestion | | tracesSampleRate | number | — | Usually 1.0 in testing, lower in production | | tracePropagationTargets | (string|RegExp)[] | SDK defaults | URLs that receive tracing headers | | replaysSessionSampleRate | number | — | Fraction of all sessions recorded | | replaysOnErrorSampleRate | number | — | Fraction of error sessions recorded | | profileSessionSampleRate | number | — | Fraction of transactions profiled (server profiling) | | tunnel | string | — | Optional ad-blocker bypass endpoint | | debug | boolean | false | Verbose SDK diagnostics |
| API | Purpose | |-----|---------| | reactRouterTracingIntegration() | Client-side tracing integration for framework mode | | sentryOnError | Hooks into React Router HydratedRouter error reporting | | createSentryHandleRequest(...) | Server request wrapper for framework entry server | | createSentryHandleError(...) | Server error handler wrapper | | wrapServerLoader(...) / wrapServerAction(...) | Manual wrapping for server loaders/actions | | sentryReactRouter(...) | Vite plugin for source maps/build integration | | sentryOnBuildEnd(...) | React Router build-end hook for source map processing |
If wizard examples were generated, open /sentry-example-page and trigger test actions.
tsxexport async function loader() { throw new Error("My first Sentry error!"); }
tsximport * as Sentry from "@sentry/react-router"; export async function loader() { return Sentry.startSpan( { op: "test", name: "My First Test Transaction" }, () => { throw new Error("My first Sentry error!"); }, ); }
javascriptSentry.logger.info("User example action completed"); Sentry.logger.warn("Slow operation detected", { operation: "data_fetch", duration: 3500 }); Sentry.logger.error("Validation failed", { field: "email", reason: "Invalid email" });
Confirm in Sentry:
enableLogs: trueAfter completing React Router Framework setup:
@sentry/react).sentry-react-sdk for non-framework routing integrations.Then check companion backend coverage:
bashls ../backend ../server ../api ../go ../python 2>/dev/null cat ../go.mod ../requirements.txt ../pyproject.toml ../Gemfile ../pom.xml 2>/dev/null | head -5
| Backend detected | Suggest skill | |------------------|--------------| | Go | sentry-go-sdk | | Python | sentry-python-sdk | | Ruby | sentry-ruby-sdk | | Node backend services | sentry-node-sdk | | Java services | Use @sentry/java docs |
| Issue | Solution | |-------|----------| | entry.client.tsx / entry.server.tsx missing | Run npx react-router reveal first | | Client errors missing | Ensure HydratedRouter includes onError={Sentry.sentryOnError} | | Server errors missing | Use createSentryHandleRequest and createSentryHandleError wrappers | | Custom server handlers bypass Sentry | Use wrapSentryHandleRequest and manual captureException in custom handleError | | Source maps not uploaded | Verify sentryReactRouter plugin config and sentryOnBuildEnd hook | | SENTRY_AUTH_TOKEN undefined in Vite config | Load env vars in config or use .env.sentry-build-plugin | | Incomplete server auto-instrumentation | Prefer NODE_OPTIONS='--import ./instrument.server.mjs' startup | | Profiling data missing | Confirm @sentry/profiling-node installed and nodeProfilingIntegration enabled | | Running unsupported Node auto-instrumentation version | Use instrumentation API/manual wrappers as documented | | Non-framework app configured with @sentry/react-router | Switch to sentry-react-sdk + @sentry/react for v5/v6/v7 non-framework routes |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 20,026 | 2,578 | -87% | 1 | 1 | 0% | 3,900 | 4,001 | +3% | 0 | 0 | — |
case-02 | fail→fail | 19,695 | 5,341 | -73% | 1 | 1 | 0% | 4,282 | 3,973 | -7% | 0 | 0 | — |
case-03 | fail→fail | 16,804 | 5,724 | -66% | 1 | 1 | 0% | 3,760 | 3,997 | +6% | 0 | 0 | — |
case-04 | pass→pass | 4,261 | 2,563 | -40% | 1 | 1 | 0% | 834 | 4,181 | +401% | 0 | 0 | — |
case-05 | fail→pass | 12,158 | 4,073 | -66% | 1 | 1 | 0% | 2,407 | 4,461 | +85% | 0 | 0 | — |
case-06 | fail→pass | 10,650 | 5,133 | -52% | 1 | 1 | 0% | 1,963 | 4,754 | +142% | 0 | 0 | — |
case-07 | pass→pass | 11,536 | 6,463 | -44% | 1 | 1 | 0% | 2,148 | 5,013 | +133% | 0 | 0 | — |
case-08 | fail→pass | 3,341 | 3,484 | +4% | 1 | 1 | 0% | 626 | 4,397 | +602% | 0 | 0 | — |
case-09 | fail→pass | 19,205 | 3,298 | -83% | 1 | 1 | 0% | 3,724 | 4,319 | +16% | 0 | 0 | — |
case-10 | fail→pass | 13,325 | 4,793 | -64% | 1 | 1 | 0% | 2,684 | 4,685 | +75% | 0 | 0 | — |
case-11 | pass→pass | 9,444 | 3,512 | -63% | 1 | 1 | 0% | 2,083 | 4,433 | +113% | 0 | 0 | — |
case-12 | fail→pass | 7,756 | 3,059 | -61% | 1 | 1 | 0% | 1,487 | 4,348 | +192% | 0 | 0 | — |
case-13 | pass→pass | 6,174 | 3,132 | -49% | 1 | 1 | 0% | 1,130 | 4,293 | +280% | 0 | 0 | — |
case-14 | fail→fail | 12,327 | 10,163 | -18% | 1 | 1 | 0% | 2,039 | 5,731 | +181% | 0 | 0 | — |
case-15 | pass→pass | 11,295 | 5,040 | -55% | 1 | 1 | 0% | 2,043 | 4,705 | +130% | 0 | 0 | — |
case-16 | fail→pass | 15,493 | 8,552 | -45% | 1 | 1 | 0% | 3,028 | 5,352 | +77% | 0 | 0 | — |
case-17 | fail→pass | 15,144 | 8,803 | -42% | 1 | 1 | 0% | 3,058 | 5,542 | +81% | 0 | 0 | — |
case-18 | pass→pass | 6,283 | 2,690 | -57% | 1 | 1 | 0% | 1,197 | 4,192 | +250% | 0 | 0 | — |
case-19 | pass→pass | 13,590 | 4,748 | -65% | 1 | 1 | 0% | 2,674 | 4,610 | +72% | 0 | 0 | — |
case-20 | pass→pass | 13,644 | 7,030 | -48% | 1 | 1 | 0% | 2,844 | 5,157 | +81% | 0 | 0 | — |
case-21 | pass→pass | 8,879 | 5,581 | -37% | 1 | 1 | 0% | 1,695 | 4,751 | +180% | 0 | 0 | — |
case-22 | pass→pass | 8,989 | 4,120 | -54% | 1 | 1 | 0% | 1,815 | 4,573 | +152% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +36 percentage points is the difference between those two pass rates over the 20 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.