@interfere/vite wires Interfere into your Vite build and your running app together. You set it up once: drop in the plugin and start the SDK before render. After that, Interfere records everything the app produces (errors, sessions, traces, and logs) with no sampling and no knobs to turn. It then collapses related symptoms into one problem, weighs how much it matters, and works out the cause for you.
It works for a plain single-page app and for server-rendered setups like TanStack Start. This page covers the install plus the handful of settings most teams actually touch.
You’ll need a surface public key (
interfere_pub_<region>_…) from Surfaces. For source-map upload and release tracking you’ll also want an Interfere API key (interfere_secret_<region>_…). See Environment variables.Prerequisites
- A Vite app using React
>= 19 - Node.js
>= 20
Quick start
These four steps cover a single-page app. If you server-render (TanStack Start, for example), do these first, then Server-side rendering.1
Install the packages
2
Add the plugin to your Vite config
The plugin stamps your public key into the build and, with
build.sourcemap on, uploads source maps so a production stack trace points back to your original code instead of minified output.vite.config.ts
3
Start the SDK before render
Call
init() before you mount React, so the SDK is capturing the moment your app loads.src/main.tsx
4
Add the provider
Wrap your app once so components can reach the SDK through hooks.
src/app.tsx
Environment variables
Configuration
The defaults are meant to be left alone, so plenty of apps never open this section. When you do need it,serviceName lives on the init() call from step 3, and what’s captured is set on the provider.
Name your app
Running more than one app on Interfere, like a storefront and an admin panel? Give each one aserviceName so its problems, sessions, and metrics stay attributed to it.
src/main.tsx
string
default:"interfere-sdk"
A stable name for this app. Interfere uses it to keep each surface’s data separate, and to
correlate the same issue across surfaces into one problem.
Environments
Interfere tags everything it captures with the environment it ran in, and labels each release the same way. In the dashboard, releases carry an environment badge and you can filter by environment, so production data and preview data stay apart. Set it withINTERFERE_ENVIRONMENT:
production, staging, preview, canary, or whatever you name it. If you don’t set it, Interfere falls back to VERCEL_ENV, then NODE_ENV, then development. The plugin stamps the value into your build, so it needs no VITE_ prefix.
Custom ingest domain
Point the browser SDK at a subdomain of your own site to survive ad-blocker deny-lists (no server component involved), or at a regional endpoint. SetapiHost on the plugin:
vite.config.ts
apiHost (or VITE_INTERFERE_API_URL) to that URL. Ingest requests never carry cookies.
Choose what’s captured
Interfere captures every signal below unless you say otherwise. Switch any of them off with the provider’splugins prop, for instance to drop session replay when recordings aren’t welcome:
src/app.tsx
object
Each signal can be toggled on or off. All default to on.
errors: uncaught exceptionslogs: console outputdevice: device and browser infopageEvents: pageviews and clicksrageClick: rage-click detectionreplay: session replay
Identity
Sessions start out anonymous. Attach the signed-in user and a problem will show you exactly who ran into it in Users, by name and email instead of a random id. Callidentity.set() from the useInterfere hook once you have a user:
string
required
Your internal, stable user ID. Use this rather than the email.
object
required
Where the identity came from.
type: one ofclerk,auth0, orcustomname: the provider’s display name, for example“Clerk”
string
Display name.
string
Email address.
string
Avatar URL.
object
Any extra metadata you want attached to the user (
Record<string, unknown>).identity.set() is deduplicated per session, so calling it on every render is fine. Identity
clears automatically when the session rotates.Consent
Everything captures out of the box. To tie that to a cookie banner or a privacy choice, hand the provider aconsent object. From then on only essential capture (error tracking and logs) runs, plus whichever categories you switch on:
Update consent at runtime through the same hook:
Mask replay data
Session replay records the DOM, so anything on screen can land in a recording. Password inputs are masked for you, and three privacy classes are always active — they’re hard-wired, so no config can turn them off. Add a class to any element to redact more; nothing else to set up.replay config to the provider’s plugins. Only passwords are masked by default; set maskAllInputs: true for a stricter baseline that redacts every input.
src/app.tsx
For finer control,
plugins.replay also forwards raw rrweb options — maskTextSelector / blockSelector / ignoreSelector to target elements by CSS selector, maskInputFn / maskTextFn to transform masked values, and recordCanvas. These are additive; the interfere-* classes still apply.Report a handled error
Uncaught errors are already covered. For one you catch and handle yourself but still want on the record, callcapture:
Server-side rendering
If you server-render with TanStack Start (or another Nitro-based setup), do the Quick start steps, then boot server instrumentation and split the browserinit() behind a runtime guard. Telemetry posts directly from the browser — set apiHost on the plugin for an ad-blocker-resistant subdomain.
1
Boot server instrumentation and browser init from the router
Call You can drop step 3 (
register() on the server (OTel bootstrap) and init() in the browser. Guard on typeof window so each half only runs where it should.src/router.tsx
init() in main.tsx) from the Quick start — the router handles it now.2
Wrap the root route with the provider
src/routes/__root.tsx
captureError:
Other frameworks
Next.js
@interfere/next: a build plugin, server instrumentation, and a provider for the App Router.NestJS
@interfere/nest: a backend module plus instrument.ts for server error capture.FAQ
Should I keep development data out of my dashboard?
Should I keep development data out of my dashboard?
The Vite SDK runs whenever it’s loaded, including locally. To capture only in production builds, gate it:
init({ enabled: import.meta.env.PROD }).Some telemetry is blocked by ad-blockers on my SPA.
Some telemetry is blocked by ad-blockers on my SPA.
Set
apiHost on the plugin to a subdomain of your own site — a CNAME to the target shown in your dashboard. Telemetry then posts to your own origin, no server route needed.Do you handle the same issue across multiple apps?
Do you handle the same issue across multiple apps?
Yes. Give each app its own
serviceName. When the same issue hits more than one surface,
Interfere correlates it into a single problem instead of a separate alert per app.Can I ship errors only, without analytics or replay?
Can I ship errors only, without analytics or replay?
Yes. Disable the signals you don’t want with the provider’s
plugins prop, for example <InterfereProvider plugins={{ replay: false, pageEvents: false }}>. To drop browser tracing from the bundle entirely, pass init({ tracing: false }).