diff --git a/concepts.mdx b/concepts.mdx index 0e8fd64..c7b8663 100644 --- a/concepts.mdx +++ b/concepts.mdx @@ -29,16 +29,18 @@ Interfere builds a problem by matching evidence that shares the same root cause. Every problem has a status that tells you where it is and whether it needs you. -| Status | What it means | Your move | +| Status | What it means | Who sets it | | --- | --- | --- | -| Investigating | Interfere is working out what happened and why. If it can't reach a conclusion on its own, it flags the problem for you. | Usually nothing | -| Active | A confirmed problem, explained and waiting on a fix. | Decide on the fix | -| In recovery | The problem looks like it's clearing on its own. Interfere watches before closing it. | Nothing | -| Needs attention | Likely a regression that Interfere isn't sure about. | Confirm it | -| Resolved | Marked fixed. Interfere keeps watching in case it returns. | You set this | -| Dismissed | Not worth acting on. | You set this | - -You dismiss a problem when it isn't worth acting on. It leaves your active list, and Interfere still remembers it, so you keep the history if it ever returns. You mark a problem resolved once you've shipped a fix; Interfere then watches later releases and reopens it as a [regression](#regression) if the same issue comes back. +| Investigating | Interfere is working out what happened and why. If it can't reach a conclusion on its own, it flags the problem for you. | Interfere | +| Active | A confirmed problem, explained and waiting on a fix. | Interfere | +| In recovery | The problem looks like it's clearing on its own. Interfere watches for a while before it closes it out. | Interfere | +| Needs attention | Likely a regression that Interfere isn't sure about. | Interfere | +| Resolved | The problem has stopped and stayed gone. Interfere keeps watching in case it returns. | Interfere | +| Dismissed | Not worth acting on. | You | + +Interfere drives status as it investigates and watches a problem. It works through Investigating, marks a problem Active once it's confirmed, and marks it Resolved when the problem stops recurring. If the same issue comes back on a later release, Interfere reopens the resolved problem as a [regression](#regression). + +The one status you set yourself is Dismissed. Dismiss a problem when it isn't worth acting on. It leaves your active list, and Interfere still keeps the record, so you have the history if it ever returns. See [the problem view](/product/problems#work-the-problem) for how to dismiss. ### Fixes diff --git a/images/inbox.png b/images/inbox.png index 9e5b251..7af026a 100644 Binary files a/images/inbox.png and b/images/inbox.png differ diff --git a/images/problem-detail.png b/images/problem-detail.png index 0ac1fb2..9916d9b 100644 Binary files a/images/problem-detail.png and b/images/problem-detail.png differ diff --git a/product/activity.mdx b/product/activity.mdx index 3f47edd..0405831 100644 --- a/product/activity.mdx +++ b/product/activity.mdx @@ -1,5 +1,6 @@ --- title: "Activity" +icon: "bell" description: "A running feed of what's happening across your workspace." --- diff --git a/product/compliance.mdx b/product/compliance.mdx index d5519d4..d3fba5a 100644 --- a/product/compliance.mdx +++ b/product/compliance.mdx @@ -1,5 +1,6 @@ --- title: "Compliance" +icon: "shield-check" description: "Interfere's certifications, reports, and data handling." --- diff --git a/product/inbox.mdx b/product/inbox.mdx index 2e62723..44dc1f0 100644 --- a/product/inbox.mdx +++ b/product/inbox.mdx @@ -1,9 +1,10 @@ --- title: "Inbox" +icon: "inbox" description: "Every problem in your product, in one place to triage and work." --- -The [Inbox](https://interfere.com/~/*) is where you see and work every [problem](/concepts#problem) Interfere has found. Each one arrives already grouped across your users and surfaces and investigated, so you spend your time deciding what to do rather than digging through stack traces. Because problems are de-duplicated, the Inbox stays a short list of real issues instead of a wall of alerts. +Interfere fills your [Inbox](https://interfere.com/~/*) for you. You never open a ticket here. Every [problem](/concepts#problem) surfaces on its own as Interfere processes your events, already grouped across your users and surfaces and already investigated. Your work starts at triage, not at filing. Because problems are de-duplicated, the Inbox stays a short list of real issues instead of a wall of alerts. ![Inbox board showing problems grouped by status](/images/inbox.png) @@ -15,3 +16,7 @@ The [Inbox](https://interfere.com/~/*) is where you see and work every [problem] ## Statuses Every problem has a status that tells you where it is and whether it needs you, from "under investigation" while Interfere works out the cause, to "needs attention" when it wants you to confirm a likely regression. See [Statuses](/concepts#statuses) for the full set and your move on each. + +## Act in bulk + +Select several problems from the list to handle them together. You can assign them, set their priority, or subscribe in one action instead of opening each one. diff --git a/product/problems.mdx b/product/problems.mdx index 18160cf..37c2c03 100644 --- a/product/problems.mdx +++ b/product/problems.mdx @@ -1,5 +1,6 @@ --- title: "The problem view" +icon: "bug" sidebarTitle: "Problem view" description: "Everything you need to understand and fix one problem, with a timeline at its heart." --- @@ -25,11 +26,20 @@ The timeline is the heart of the problem view: one chronological thread of the i - **Relevant sessions.** Jump straight to the [session replays](https://interfere.com/~/*/users) where the problem actually appeared, so you spend your time on where it shows up in a real user's flow. - **Filtering.** Filter the timeline down to the part you care about when there's a lot going on. -## Collaborate +## Work the problem -A problem is rarely one person's job, so the timeline is where your team works it together. +You don't file problems, and you rarely set their status by hand. Interfere surfaces them from your events and moves them through their [statuses](/concepts#statuses) on its own as it investigates. Your job is to direct and decide. From the problem view you can: -- **Assign it.** Hand a problem to the right teammate. -- **Discuss inline.** Comment and mention people on the timeline to pull in whoever's needed, from the engineer who owns the code to a designer or PM. -- **Get notified.** Interfere notifies the right people when a problem needs them. Choose where those notifications go in [Alerts](https://interfere.com/~/*/settings/alerts). -- **Carry it into Slack.** Mentions and assignments reach you as Slack messages, and you can keep the conversation there. See [Slack](/integrations/slack) or open the [Slack integration](https://interfere.com/~/*/settings/integrations/slack). +- **Assign it.** Hand the problem to the right teammate. Press a to open the assignee picker. +- **Set priority.** Mark it high, medium, or low so the team knows what to pick up first. Press p to set it. +- **Edit the title or description.** Interfere writes both for you. Tighten either one if you want it to read a certain way for your team. +- **Discuss inline.** Comment on the timeline and @mention people to pull in whoever's needed, from the engineer who owns the code to a designer or PM. +- **Subscribe.** Follow a problem to get its updates, or unsubscribe to step back. Press s to toggle it. +- **Dismiss it.** When a problem isn't worth acting on, dismiss it to clear it from your active list. Interfere keeps the record in case it returns. +- **Archive it.** Remove a problem you don't want to see at all. + +Interfere handles the rest of the lifecycle. It marks a problem resolved once the issue stops recurring, and reopens it as a [regression](/concepts#regression) if it comes back on a later release. You never mark something resolved by hand. + +## Get notified + +Interfere notifies the right people when a problem needs them. Choose where those notifications go in [Alerts](https://interfere.com/~/*/settings/alerts). Mentions and assignments also reach you as Slack messages, and you can keep the conversation there. See [Slack](/integrations/slack) or open the [Slack integration](https://interfere.com/~/*/settings/integrations/slack). diff --git a/product/security.mdx b/product/security.mdx index 865c619..9eba0fb 100644 --- a/product/security.mdx +++ b/product/security.mdx @@ -1,6 +1,8 @@ --- -title: "Security" -description: "How you sign in to Interfere, how team access is controlled, and where we stand on compliance." +title: "Authentication & access" +sidebarTitle: "Authentication" +icon: "lock" +description: "How you sign in to Interfere, and how team access is controlled." --- How your team signs in, and who can reach what. For certifications and reports, see [Compliance](/product/compliance). diff --git a/product/settings.mdx b/product/settings.mdx index 84c6367..ac3a47e 100644 --- a/product/settings.mdx +++ b/product/settings.mdx @@ -1,5 +1,6 @@ --- title: "Settings" +icon: "settings" description: "Workspace, profile, alerts, integrations, team, and billing." --- diff --git a/product/surfaces.mdx b/product/surfaces.mdx index 637240b..c4df3b3 100644 --- a/product/surfaces.mdx +++ b/product/surfaces.mdx @@ -1,5 +1,6 @@ --- title: "Surfaces" +icon: "layers" description: "Manage the apps Interfere watches, their keys, environments, and releases." --- diff --git a/product/users.mdx b/product/users.mdx index 3831b09..e19c06a 100644 --- a/product/users.mdx +++ b/product/users.mdx @@ -1,5 +1,6 @@ --- title: "Users" +icon: "users" description: "The people using your product, and session replays of what they did." --- diff --git a/quickstart.mdx b/quickstart.mdx index 3084927..aaa9226 100644 --- a/quickstart.mdx +++ b/quickstart.mdx @@ -18,15 +18,35 @@ Work through this checklist end to end and you'll have problems showing up in yo - Paste this into your coding agent (Cursor, Claude Code, and the like) and let it wire everything up: + Point your coding agent at the Interfere install prompt and it wires everything up. Run the command for your agent: - ```text - Set up the Interfere SDK in this project. Detect my framework - (Next.js, Vite, or NestJS) and follow the matching Interfere - install guide step by step. Read INTERFERE_PUBLIC_KEY from my - environment and never print my keys. + + + ```bash Claude Code + curl -sL https://interfere.com/prompts/onboarding/v8/onboarding-nextjs.md | claude -p "Add Interfere to this codebase" + ``` + + ```bash Codex + codex -s workspace-write -a on-request "$(curl -sL https://interfere.com/prompts/onboarding/v8/onboarding-nextjs.md) Add Interfere to this codebase" ``` + ```bash Cursor + cursor-agent --print --force "$(curl -sL https://interfere.com/prompts/onboarding/v8/onboarding-nextjs.md) Add Interfere to this codebase" + ``` + + + + On Vite, swap `onboarding-nextjs.md` for `onboarding-vite.md`. Want to read the prompt first? Open it directly: + + + + Covers Next.js, NestJS, and other Node backends. + + + Covers Vite and React apps. + + + You can also open **Ask AI** at the top of these docs and ask it to install Interfere in your project. diff --git a/sdk/nestjs.mdx b/sdk/nestjs.mdx index fbfb642..ae0bd12 100644 --- a/sdk/nestjs.mdx +++ b/sdk/nestjs.mdx @@ -1,5 +1,6 @@ --- title: "NestJS" +icon: "/icons/tech/nestjs/transparent.svg" description: "Instrument your NestJS backend so server errors reach Interfere with full stack traces." --- @@ -125,5 +126,5 @@ const order = await withSpan("checkout.submit", () => submitOrder(cart)); | --- | --- | --- | | `INTERFERE_PUBLIC_KEY` | Yes | Your [surface public key](https://interfere.com/~/*/surfaces) (`interfere_pub__…`). Routes telemetry to your project. | | `INTERFERE_API_KEY` | For releases | Used by the [CLI](/integrations/cli) to upload source maps (`interfere_secret__…`). A build-time secret; keep it in CI. | -| `INTERFERE_ENVIRONMENT` | No | Environment label for releases. Falls back to `VERCEL_ENV`, then `NODE_ENV`. | +| `INTERFERE_ENVIRONMENT` | No | Labels this process's telemetry and releases (`production`, `staging`, or a label you choose). Falls back to `VERCEL_ENV`, then `NODE_ENV`, then `development`. Interfere drops the `development`, `local`, and `test` environments before ingestion, so set a real one to capture from it. | | `INTERFERE_DEBUG` | No | Set to `1` for lifecycle logs while setting up. | diff --git a/sdk/next-js.mdx b/sdk/next-js.mdx index 0df1ab1..0b09f6a 100644 --- a/sdk/next-js.mdx +++ b/sdk/next-js.mdx @@ -1,5 +1,6 @@ --- title: "Next.js" +icon: "/icons/tech/nextjs/currentcolor.svg" mode: "default" description: "Add error tracking, session replay, and product analytics to your Next.js app with a single provider." --- @@ -110,6 +111,7 @@ Five steps, each wired once. After this you don't touch it again. | ------------------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `INTERFERE_PUBLIC_KEY` | Yes | Your [surface public key](https://interfere.com/~/*/surfaces) (`interfere_pub__…`, where `` is `us` or `eu`). Safe to expose; it only authorizes ingestion. | | `INTERFERE_API_KEY` | For releases | Interfere API key (`interfere_secret__…`). A **server-side build credential** for source-map upload and release metadata. Never expose it in browser code. | +| `INTERFERE_ENVIRONMENT` | No | Labels this deployment's telemetry and releases (`production`, `staging`, `preview`, or a label you choose). Read at build time and stamped into the bundle, so it needs no `NEXT_PUBLIC_` prefix. Defaults to `VERCEL_ENV`, then `NODE_ENV`, then `development`. See [Environments](#environments). | | `NEXT_PUBLIC_INTERFERE_ROUTE_PREFIX` | No | Override the proxy route prefix. Defaults to `/api/interfere`. See [Custom route prefix](#custom-route-prefix). | @@ -136,6 +138,26 @@ init({ serviceName: "@acme/storefront" }); 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 with `INTERFERE_ENVIRONMENT`: + +```env +INTERFERE_ENVIRONMENT=production +``` + +The label is free-form: `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`. On Vercel you usually get the right value without doing anything. + + + Interfere reads this at build time and bakes it into your bundle, so it does not need a `NEXT_PUBLIC_` prefix. + + + + Interfere drops local-like environments (`development`, `local`, `test`) before ingestion, so everyday local traffic never reaches your dashboard. An app with no environment set defaults to `development` and is filtered out, which is one reason nothing shows up until you deploy. Set a real environment, or turn off environment filtering for the surface, to capture from one. + + ### 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: @@ -288,11 +310,11 @@ The SDK proxies telemetry through `/api/interfere` by default. Move it to any pa ## Other frameworks - + `@interfere/vite`: a Vite plugin plus `init()` before render. Works for SPA and SSR. - + `@interfere/vite`: the same plugin, with a server route for proxying. @@ -305,7 +327,7 @@ The SDK proxies telemetry through `/api/interfere` by default. Move it to any pa - 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`. + 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`. Interfere also drops the `development`, `local`, and `test` environments before ingestion, so set a real [environment](#environments) too if you want that data to land. diff --git a/sdk/vite.mdx b/sdk/vite.mdx index f526e0d..8dcb98b 100644 --- a/sdk/vite.mdx +++ b/sdk/vite.mdx @@ -1,5 +1,6 @@ --- title: "Vite (React)" +icon: "/icons/tech/vite/transparent.svg" description: "Install the Interfere SDK in your Vite app. One-time setup, then Interfere captures everything you ship." sidebarTitle: "Vite" --- @@ -105,6 +106,7 @@ These four steps cover a single-page app. If you server-render (TanStack Start, | --------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | | `VITE_INTERFERE_PUBLIC_KEY` | Yes | Your [surface public key](https://interfere.com/~/*/surfaces) (`interfere_pub__…`, where `` is `us` or `eu`). Safe to expose; the plugin stamps it into your build. | | `INTERFERE_API_KEY` | For releases | Interfere API key (`interfere_secret__…`). A **build-time credential** for source-map upload and release metadata. | +| `INTERFERE_ENVIRONMENT` | No | Labels this build's telemetry and releases (`production`, `staging`, `preview`, or a label you choose). The plugin stamps it into the build, so it needs no `VITE_` prefix. Defaults to `VERCEL_ENV`, then `NODE_ENV`, then `development`. See [Environments](#environments). | Only `VITE_`-prefixed variables reach the browser. Keep `INTERFERE_API_KEY` out of any `VITE_` @@ -128,6 +130,22 @@ init({ serviceName: "@acme/storefront" }); 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 with `INTERFERE_ENVIRONMENT`: + +```env +INTERFERE_ENVIRONMENT=production +``` + +The label is free-form: `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. + + + Interfere drops local-like environments (`development`, `local`, `test`) before ingestion, so everyday local traffic never reaches your dashboard. A build with no environment set defaults to `development` and is filtered out. Set a real environment, or turn off environment filtering for the surface, to capture from one. + + ### Choose what's captured Interfere captures every signal below unless you say otherwise. Switch any of them off with `plugins`, for instance to drop session replay when recordings aren't welcome: diff --git a/style.css b/style.css index 4384a0f..778a6f8 100644 --- a/style.css +++ b/style.css @@ -50,6 +50,15 @@ code-group, font-variant-ligatures: none; } +/* Keyboard keys: force Berkeley Mono to match the app UI. Mintlify styles + `kbd` with its own font, so this needs to win on specificity. */ +kbd { + font-family: + "BerkeleyMono", ui-monospace, "SFMono-Regular", "Menlo", "Monaco", "Consolas", + "Liberation Mono", "Courier New", monospace !important; + font-variant-ligatures: none; +} + /* --- Selection ------------------------------------------------------------ Inverted/standout treatment from the design system (kept monochrome to match the docs palette). */ @@ -103,6 +112,15 @@ code-group, background: rgba(255, 255, 255, 0.7) !important; /* white-a9 */ } +/* Align the CTA's right edge with the content panel. The topbar gutter + (lg:px-7) stops the button ~20px short of the panel's right edge, so pull it + back into line. Only applies where the button shows (lg and up). */ +@media (min-width: 1024px) { + #topbar-cta-button { + margin-right: -1.25rem !important; + } +} + /* --- Surfaces ------------------------------------------------------------- Soften borders and round surfaces to match the design system's hairline borders (gray-a3) and rounded containers (radius-2xl = 12px). */ @@ -114,3 +132,78 @@ pre { :not(pre) > code { border-radius: 6px !important; } + +/* --- Dark-mode logos ------------------------------------------------------ + The `currentcolor` brand marks (Next.js, Vercel, GitHub, …) render as solid + black when Mintlify inlines them as , so they vanish on the dark + background. They're single-color marks, so inverting them to white in dark + mode is safe. Colored variants (`transparent`, `original`) are left alone, + since inverting those would wreck their brand colors. */ +.dark img[src$="/currentcolor.svg"] { + filter: invert(1); +} + +/* --- TechIcon light/dark swap --------------------------------------------- + Backs the light/dark pair emitted by components/TechIcon.tsx so it + shows the right variant per theme. */ +.tech-icon__image--dark { + display: none; +} + +.dark .tech-icon__image--light { + display: none; +} + +.dark .tech-icon__image--dark { + display: inline-block; +} + +/* --- Page subtitle -------------------------------------------------------- + The description under the H1 uses semi-medium weight, matching the app. */ +#content-area header p, +header h1 + p { + font-weight: 550; +} + +/* --- Sidebar category titles ---------------------------------------------- + The nav group headers (Getting Started, Product, SDKs, Integrations) use + semi-medium weight, matching the app. Scoped to the sidebar nav so page + headings aren't affected. */ +#sidebar h3, +#sidebar [role="heading"], +[aria-label="Pages"] h3, +[aria-label="Pages"] [role="heading"] { + font-weight: 550 !important; +} + +/* --- Table identifier tokens ---------------------------------------------- + Mintlify breaks inline code mid-token in table cells (INTERFERE_PUBLIC_KE / + Y). Keep first-column identifiers on one line so env-var names read cleanly; + description-column code is left free to wrap. */ +table td:first-child code, +table th:first-child code { + white-space: nowrap; +} + +/* --- Content width -------------------------------------------------------- + The theme caps the article at max-w-xl (576px), which is too narrow for our + env-var tables and code. Widen it, and trim the oversized desktop gutters to + give the extra room back to content. The right-hand "On this page" column + still fits alongside. */ +#content-area { + max-width: 48rem !important; +} + +@media (min-width: 1024px) { + #content-container { + padding-left: 2.5rem !important; + padding-right: 2.5rem !important; + } +} + +/* Drop the right/bottom gutter on the main content wrapper so it sits flush + against the viewport edge. (Left padding is left intact.) */ +.lg\:flex-1.lg\:overflow-x-clip > div { + padding-right: 0 !important; + padding-bottom: 0 !important; +}