diff --git a/docs/platforms/javascript/guides/tanstackstart-react/features/createSentryTunnelRoute.mdx b/docs/platforms/javascript/guides/tanstackstart-react/features/createSentryTunnelRoute.mdx new file mode 100644 index 0000000000000..0242e493afbca --- /dev/null +++ b/docs/platforms/javascript/guides/tanstackstart-react/features/createSentryTunnelRoute.mdx @@ -0,0 +1,58 @@ +--- +title: createSentryTunnelRoute +description: "Learn how to manually define a Sentry tunnel route in your TanStack Start app." +--- + + + + + If you can use the `sentryTanstackStart` Vite plugin, prefer its + [`tunnelRoute`](/platforms/javascript/guides/tanstackstart-react/features/sentryTanstackStart/#tunnel-route) + option. It registers the route for you and automatically wires up the client + `tunnel` option. Use `createSentryTunnelRoute` only when you need full control over + the route file, the DSN allowlist, or can't use the Vite plugin. + + +The `createSentryTunnelRoute` helper returns a TanStack Start server-route configuration with a `POST` handler that forwards Sentry envelopes to Sentry's ingest servers. Use it inside a file route to expose a same-origin tunnel endpoint. + +## Usage + +Create a server route at the path you want to tunnel through, and pass the list of DSNs you want to allow: + +```typescript {filename:src/routes/monitor.ts} +import { createFileRoute } from "@tanstack/react-router"; +import * as Sentry from "@sentry/tanstackstart-react"; + +export const Route = createFileRoute("/monitor")({ + server: Sentry.createSentryTunnelRoute({ + allowedDsns: ["___PUBLIC_DSN___"], + }), +}); +``` + +Then, set the matching `tunnel` option in your client `Sentry.init()` so the browser SDK sends events to your route instead of directly to Sentry: + +```tsx {filename:src/router.tsx} {4} +Sentry.init({ + dsn: "___PUBLIC_DSN___", + // ... + tunnel: "/monitor", +}); +``` + +## Options + +### `allowedDsns` + +A list of DSN strings that the route is allowed to forward to. The route validates each incoming envelope against this list and rejects any DSN that isn't allowed. + +If `allowedDsns` is omitted or empty, the route falls back to the DSN of the active server-side Sentry SDK at runtime. If neither is available, requests to the route return a 500 response. + +```typescript {filename:src/routes/monitor.ts} +Sentry.createSentryTunnelRoute({ + allowedDsns: [ + "https://public@o0.ingest.sentry.io/1", + "https://public@o0.ingest.sentry.io/2", + ], +}); +``` diff --git a/docs/platforms/javascript/guides/tanstackstart-react/features/sentryTanstackStart.mdx b/docs/platforms/javascript/guides/tanstackstart-react/features/sentryTanstackStart.mdx index 2d4d08d5d7662..8e971320d2e54 100644 --- a/docs/platforms/javascript/guides/tanstackstart-react/features/sentryTanstackStart.mdx +++ b/docs/platforms/javascript/guides/tanstackstart-react/features/sentryTanstackStart.mdx @@ -61,3 +61,61 @@ sentryTanstackStart({ autoInstrumentMiddleware: false, }), ``` + +## Tunnel Route + + + +The `tunnelRoute` option registers a same-origin TanStack Start server route that forwards Sentry envelopes to Sentry's ingest servers. It also automatically sets the client `tunnel` option in `Sentry.init()` so browser events go through that route. This helps avoid ad blockers and corporate firewalls that block requests to `*.sentry.io`. + +`tunnelRoute` accepts three shapes: + +### `tunnelRoute: true` (recommended) + +Generates an opaque, unguessable route path for each dev session and production build. Because the path changes between builds, ad blockers can't reliably target it. + +```typescript {filename:vite.config.ts} +sentryTanstackStart({ + tunnelRoute: true, +}), +``` + +### Static path + +Pass a string to use a fixed route path. This is easier to reason about, but a known path is easier for ad blockers to add to a list. + +```typescript {filename:vite.config.ts} +sentryTanstackStart({ + tunnelRoute: "/monitor", +}), +``` + +### Object form + +Use the object form to control the DSN allowlist or set a static path explicitly: + +```typescript {filename:vite.config.ts} +sentryTanstackStart({ + tunnelRoute: { + allowedDsns: ["___PUBLIC_DSN___"], + path: "/monitor", + }, +}), +``` + +- **`allowedDsns`** — only envelopes targeting one of these DSNs are forwarded. If omitted or empty, the route falls back to the DSN of the active server-side Sentry SDK at runtime. +- **`path`** — the public route path. If omitted, an opaque path is generated (same behavior as `tunnelRoute: true`). + + + If you also pass `tunnel` to `Sentry.init()`, the runtime option wins and the + managed tunnel route is bypassed. The SDK logs a warning when this happens. + + + + When using `tunnelRoute: true` (or the object form without `path`), the + generated path changes for each dev session and each production build. Don't + hard-code it elsewhere in your app or infrastructure. + diff --git a/docs/platforms/javascript/guides/tanstackstart-react/index.mdx b/docs/platforms/javascript/guides/tanstackstart-react/index.mdx index 1ce1a5de966b3..a5dec4c6e09d0 100644 --- a/docs/platforms/javascript/guides/tanstackstart-react/index.mdx +++ b/docs/platforms/javascript/guides/tanstackstart-react/index.mdx @@ -347,7 +347,28 @@ If you need more control over the upload process, see our [source maps guide](/p ## Step 5: Avoid Ad Blockers With Tunneling (Optional) - +Ad blockers and corporate firewalls often block requests to `*.sentry.io`, which can cause events to be dropped before they reach Sentry. To work around this, you can tunnel events through a same-origin route in your TanStack Start app. + +The `sentryTanstackStart` Vite plugin can register a tunnel route for you and automatically wire up the client `tunnel` option: + +```typescript {filename:vite.config.ts} {9} +import { defineConfig } from "vite"; +import { tanstackStart } from "@tanstack/react-start/plugin/vite"; +import { sentryTanstackStart } from "@sentry/tanstackstart-react/vite"; + +export default defineConfig({ + plugins: [ + tanstackStart(), + sentryTanstackStart({ + tunnelRoute: true, + }), + ], +}); +``` + +With `tunnelRoute: true`, an opaque route path is generated for each dev session and production build, making it harder for ad blockers to target. See the [`sentryTanstackStart`](/platforms/javascript/guides/tanstackstart-react/features/sentryTanstackStart/#tunnel-route) feature page for static paths and the full set of options. + +If you can't use the Vite plugin, or you need full control over the route file and DSN allowlist, use [`createSentryTunnelRoute`](/platforms/javascript/guides/tanstackstart-react/features/createSentryTunnelRoute/) to define the route yourself. ## Step 6: Verify