Skip to main content
@interfere/next connects your Next.js app to Interfere. It’s a one-time install: add a few lines, ship as usual, and Interfere captures everything your app emits (errors, sessions, traces, and logs) with no sampling and nothing to tune. From there, Interfere groups related symptoms into a single problem, decides how much it matters, and investigates the cause for you. This page covers the install and the handful of settings most teams actually touch: naming your app, identifying your users, and respecting consent.
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

  • Next.js >= 16 (App Router)
  • React >= 19
  • Node.js >= 20

Quick start

Five steps, each wired once. After this you don’t touch it again.
1

Install the package

npm install @interfere/next
2

Wrap your Next.js config

This lets Interfere upload source maps at build time, so a production stack trace points back to your original code instead of minified output. It also tags each build as a release.
next.config.ts
import { withInterfere } from "@interfere/next/config";
import type { NextConfig } from "next";

const config: NextConfig = {};

export default withInterfere(config);
3

Wire server instrumentation

So server-side errors get captured too, not just client-side ones. That covers Server Components, route handlers, and server actions.
instrumentation.ts
export { onRequestError } from "@interfere/next/server";
4

Mount the ingest route

Telemetry is sent through your own domain, so ad-blockers and CORS don’t drop it. The path must match your route prefix (default /api/interfere).
app/api/interfere/[[...path]]/route.ts
export * from "@interfere/next/route-handler";
5

Add the provider

Starts the SDK in the browser and begins capturing. Wrap your app once, at the root layout.
app/layout.tsx
import { InterfereProvider } from "@interfere/next/provider";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <InterfereProvider>{children}</InterfereProvider>
      </body>
    </html>
  );
}
That’s the whole install. Run your app, trigger an error, and it shows up in your dashboard within seconds, already grouped and triaged. Open your workspace to confirm it. There’s nothing else to configure. (The SDK stays quiet outside production; see the FAQ to capture in development.)

Environment variables

VariableRequiredDescription
INTERFERE_PUBLIC_KEYYesYour surface public key (interfere_pub_<region>_…, where <region> is us or eu). Safe to expose; it only authorizes ingestion.
INTERFERE_API_KEYFor releasesInterfere API key (interfere_secret_<region>_…). A server-side build credential for source-map upload and release metadata. Never expose it in browser code.
NEXT_PUBLIC_INTERFERE_ROUTE_PREFIXNoOverride the proxy route prefix. Defaults to /api/interfere. See Custom route prefix.
INTERFERE_API_KEY is a secret. Keep it in server and CI environments only. The public key (INTERFERE_PUBLIC_KEY) is the only key that reaches the browser.

Configuration

Interfere is built to run without tuning, so most apps install it and stop here. Reach for these only when you have a specific reason.

Name your app

If you run more than one app against Interfere (a storefront and an admin panel, say), give each a serviceName so problems, sessions, and metrics are attributed to the right one. Set it in an optional instrumentation-client.ts:
instrumentation-client.ts
import { init } from "@interfere/next/instrument-client";

init({ serviceName: "@acme/storefront" });
serviceName
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.

Choose what’s captured

By default Interfere captures all of the signals below. Turn any off with plugins. For example, disable session replay if you don’t want recordings:
instrumentation-client.ts
init({ plugins: { replay: false } });
plugins
object
Each signal can be toggled on or off. All default to on.
  • errors: uncaught exceptions
  • logs: console output
  • device: device and browser info
  • pageEvents: pageviews and clicks
  • rageClick: rage-click detection
  • replay: session replay

Identity

By default a session is anonymous. Link it to your authenticated user so a problem shows you who hit it in Users, with a name and email instead of an opaque id. Call identity.set() from the useInterfere hook once your user loads:
import { useInterfere } from "@interfere/next/provider";

function SyncIdentity() {
  const { identity } = useInterfere();
  const { user } = useAuthProvider(); // Clerk, Auth0, etc.

  useEffect(() => {
    if (!user) return;
    identity.set({
      identifier: user.id,
      name: user.name,
      email: user.email,
      source: { type: "clerk", name: "Clerk" },
    });
  }, [user]);

  return null;
}
identifier
string
required
Your internal, stable user ID. Use this rather than the email.
source
object
required
Where the identity came from.
  • type: one of clerk, auth0, or custom
  • name: the provider’s display name, for example “Clerk”
name
string
Display name.
email
string
Email address.
avatar
string
Avatar URL.
traits
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.
By default all features are active. To respect a cookie banner or privacy preference, pass consent to the provider. Once you do, only essential capture (error tracking and logs) plus the categories you opt into will run:
app/layout.tsx
<InterfereProvider consent={{ analytics: true, replay: false }}>{children}</InterfereProvider>
CategoryWhat it coversGateable
necessaryError tracking, logsAlways on
analyticsPage events, rage clicks, device infoYes
replaySession replayYes
Update consent at runtime through the same hook:
const { consent } = useInterfere();

consent.set({ analytics: true, replay: true }); // selective
consent.set(); // grant everything
Interfere works with any consent platform (c15t, CookieYes, OneTrust). Map its booleans to the categories above.
To apply consent before the first render, and avoid any flash where a non-consented feature loads, pass it to init({consent}) in instrumentation-client.ts instead. The provider prop then keeps it in sync as the user changes their mind.

Report a handled error

Interfere captures uncaught errors for you. When you catch an error yourself but still want it reported, call capture on the client or captureError on the server.
import { capture } from "@interfere/next/instrument-client";

try {
  await saveDraft();
} catch (error) {
  capture(error);
}
import { captureError } from "@interfere/next/server";

export async function placeOrder() {
  try {
    await chargeCard();
  } catch (error) {
    captureError(error);
    throw error;
  }
}

Custom route prefix

The SDK proxies telemetry through /api/interfere by default. Move it to any path to get past ad-blocker deny-lists that target well-known SDK routes, or to fit your own API conventions.
1

Set the prefix

env NEXT_PUBLIC_INTERFERE_ROUTE_PREFIX=/__telemetry
2

Mount the handler at the matching path

ts app/__telemetry/[[...path]]/route.ts export * from "@interfere/next/route-handler";

Other frameworks

https://mintcdn.com/interfere/gBbwt-CEJtdTbXUl/icons/tech/vite/transparent.svg?fit=max&auto=format&n=gBbwt-CEJtdTbXUl&q=85&s=26a883debceaedbcf9187ed205eacda1

Vite + React

@interfere/vite: a Vite plugin plus init() before render. Works for SPA and SSR.
https://mintcdn.com/interfere/MgNg5VNkabABMNbR/icons/tech/tanstack/currentcolor.svg?fit=max&auto=format&n=MgNg5VNkabABMNbR&q=85&s=7d27f8690714986c74aa01641682e1b0

TanStack Start

@interfere/vite: the same plugin, with a server route for proxying.
https://mintcdn.com/interfere/-ZXFpoZpeu8oxyWI/icons/tech/nestjs/transparent.svg?fit=max&auto=format&n=-ZXFpoZpeu8oxyWI&q=85&s=24095f2ad2719279173814d170a854b0

NestJS

@interfere/nest: a backend module plus instrument.ts for server error capture.

FAQ

The SDK stays quiet when NODE_ENV !== "production", so local noise doesn’t reach your dashboard. To capture while testing, call init({ enabled: true }) in instrumentation-client.ts.
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.
It’s the recommended path. Proxying telemetry through your own origin avoids CORS and gets past ad-blockers, and it’s part of the standard install above.
Yes. Disable the signals you don’t want with plugins, for example init({ plugins: { replay: false, pageEvents: false } }). To drop browser tracing from the bundle entirely, pass init({ tracing: false }).