SDK

Framework adapters

Seven thin adapters over one core SDK. Each reports the errors your framework catches itself and, where there is a router, records navigation for Atlas.

Every adapter is published on npm next to the core SDK. Call getBrowsonic() and init() once, in the browser; the adapters find the SDK through getBrowsonic(). Do not create it with new Browsonic(): the adapters do not see such an instance and report nothing.

The adapters capture in the browser. Errors thrown on the server (during server rendering, in Next.js route handlers and server components, in Remix loaders and actions) are not captured there. When such an error reaches an error page rendered in the browser (a Next.js error.tsx, a Remix ErrorBoundary, a SvelteKit error page), it is reported with the message the framework sends to the browser.

Requirements

Every adapter needs @browsonic/sdk 3.22.0 or later, below 4.0. Install the SDK together with the adapter.

PackageCurrent versionWorks with
@browsonic/react1.5.3React 18, 19
@browsonic/vue1.6.3Vue 3.3+
@browsonic/svelte1.3.3Svelte 4, 5 (SvelteKit)
@browsonic/nextjs1.5.3Next.js 13.4+, React 18, 19
@browsonic/astro1.3.3Astro 4+
@browsonic/angular2.19.1Angular 17+
@browsonic/remix1.3.3Remix 2, React 18, 19

React

@browsonic/react — Error boundary, hooks, HOC, React Router route templates for Atlas.

A <BrowsonicErrorBoundary> that reports the render errors React catches, useBrowsonic, useUser and useCaptureError for calls from components, a withBrowsonic HOC, and useTrackPageView with routeTemplateFromMatches, which send React Router 6 and 7 route templates for Atlas.

Install

npm install @browsonic/sdk @browsonic/react

Quick start

src/main.tsx

import ReactDOM from 'react-dom/client';
import { getBrowsonic } from '@browsonic/sdk';
import { BrowsonicErrorBoundary } from '@browsonic/react';
import App from './App';

getBrowsonic().init({
  apiEndpoint: 'https://api.browsonic.com',
  appKey: 'YOUR_APP_KEY',
  apiKey: 'pk_live_YOUR_KEY',
});

ReactDOM.createRoot(document.getElementById('root')!).render(
  <BrowsonicErrorBoundary
    fallback={(error, reset) => (
      <div role="alert">
        <p>Something went wrong: {error.message}</p>
        <button onClick={reset}>Try again</button>
      </div>
    )}
  >
    <App />
  </BrowsonicErrorBoundary>,
);

Atlas route templates with React Router 6 or 7. Render this once inside the router:

import { matchRoutes, useLocation, type RouteObject } from 'react-router-dom';
import { routeTemplateFromMatches, useTrackPageView } from '@browsonic/react';

export function AtlasPageViews({ routes }: { routes: RouteObject[] }) {
  const location = useLocation();
  useTrackPageView(routeTemplateFromMatches(matchRoutes(routes, location)), undefined, location.key);
  return null;
}

With the route templates, add atlas: true to init() so they replace the URL-based page views instead of doubling them.

Vue 3

@browsonic/vue — Plugin, error boundary, composables, Vue Router instrumentation.

An app.use() plugin that installs the global error handler, a <BrowsonicErrorBoundary> component, composables for calls from components, installRouterInstrumentation for Vue Router 4 navigation breadcrumbs and route templates for Atlas, and a Pinia integration (installPiniaIntegration).

Install

npm install @browsonic/sdk @browsonic/vue

Quick start

src/main.ts

import { createApp } from 'vue';
import { getBrowsonic } from '@browsonic/sdk';
import { browsonicPlugin, installRouterInstrumentation } from '@browsonic/vue';
import App from './App.vue';
import router from './router';

const sdk = getBrowsonic();
sdk.init({
  apiEndpoint: 'https://api.browsonic.com',
  appKey: 'YOUR_APP_KEY',
  apiKey: 'pk_live_YOUR_KEY',
  atlas: true, // the router instrumentation sends route templates
});

const app = createApp(App);
app.use(browsonicPlugin, { sdk });
app.use(router);
installRouterInstrumentation(router);
app.mount('#app');

Svelte

@browsonic/svelte — SvelteKit handleError, store-driven identity, navigation breadcrumbs.

handleErrorWithBrowsonic() for SvelteKit's handleError hook, subscribeUser to follow a user store, instrumentNavigation for navigation breadcrumbs, reportErrorPage for error pages, and captureError.

Install

npm install @browsonic/sdk @browsonic/svelte

Quick start

src/hooks.client.ts

import { getBrowsonic } from '@browsonic/sdk';
import { handleErrorWithBrowsonic } from '@browsonic/svelte';

getBrowsonic().init({
  apiEndpoint: 'https://api.browsonic.com',
  appKey: 'YOUR_APP_KEY',
  apiKey: 'pk_live_YOUR_KEY',
});

export const handleError = handleErrorWithBrowsonic();

With a Svelte 5 <svelte:boundary>, call captureError from @browsonic/svelte in its onerror handler. It takes an Error, so pass error instanceof Error ? error : new Error(String(error)).

Next.js

@browsonic/nextjs — App Router error pages, Pages Router helpers, source-map upload config.

BrowsonicErrorPage and BrowsonicGlobalErrorPage for the App Router's error.tsx and global-error.tsx, Pages Router helpers (installPagesRouterAtlas, browsonicPagesErrorInitialProps), withBrowsonicConfig for source-map upload, and BrowsonicErrorBoundary, useBrowsonic, useUser, useCaptureError and withBrowsonic from @browsonic/react.

Install

npm install @browsonic/sdk @browsonic/react @browsonic/nextjs

Quick start

app/browsonic.tsx — initialises the SDK in the browser

'use client';
import { getBrowsonic } from '@browsonic/sdk';

if (typeof window !== 'undefined') {
  getBrowsonic().init({
    apiEndpoint: 'https://api.browsonic.com',
    appKey: process.env.NEXT_PUBLIC_BROWSONIC_APP_KEY!,
    apiKey: process.env.NEXT_PUBLIC_BROWSONIC_API_KEY!,
  });
}

export function Browsonic() {
  return null;
}

app/layout.tsx

import { Browsonic } from './browsonic';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Browsonic />
        {children}
      </body>
    </html>
  );
}

app/error.tsx

'use client';
import { BrowsonicErrorPage } from '@browsonic/nextjs';

export default BrowsonicErrorPage;

Use BrowsonicGlobalErrorPage the same way in app/global-error.tsx. For the Pages Router, run the same guarded init() from a module that pages/_app.tsx imports, call installPagesRouterAtlas(Router) (Router is the default export of next/router) once in a useEffect and add atlas: true to init(), and set Error.getInitialProps = browsonicPagesErrorInitialProps in pages/_error.tsx.

Astro

@browsonic/astro — An integration that loads the SDK for you, and View Transitions breadcrumbs.

browsonicIntegration, which loads and starts the SDK on every page, and navigation breadcrumbs for View Transitions.

Install

npm install @browsonic/sdk @browsonic/astro

Quick start

astro.config.mjs

import { defineConfig } from 'astro/config';
import { browsonicIntegration } from '@browsonic/astro';

export default defineConfig({
  integrations: [
    browsonicIntegration({
      apiEndpoint: 'https://api.browsonic.com',
      appKey: 'YOUR_APP_KEY',
      apiKey: 'pk_live_YOUR_KEY', // ships in every page's JavaScript: use a publishable key
      environment: 'production',
      // replay: true, // also records Session Replay
    }),
  ],
});

To set other options, register browsonicIntegration() with no options and initialise the SDK in a script in your base layout:

<script>
  import { getBrowsonic } from '@browsonic/sdk';

  getBrowsonic().init({
    apiEndpoint: 'https://api.browsonic.com',
    appKey: 'YOUR_APP_KEY',
    apiKey: 'pk_live_YOUR_KEY',
    atlas: true,
  });
</script>

The integration passes only apiEndpoint, appKey, apiKey and environment to the SDK, and the SDK logs a console warning when it starts from that injected config. Without options, browsonicIntegration() only records navigation.

Angular

@browsonic/angular — ErrorHandler drop-in, BrowsonicService, Router instrumentation.

A BrowsonicErrorHandler you provide in place of Angular's ErrorHandler, an injectable BrowsonicService, provideBrowsonic, installRouterInstrumentation for navigation breadcrumbs and route templates for Atlas, and createBrowsonicHttpReporter for HttpClient errors.

Install

npm install @browsonic/sdk @browsonic/angular

Quick start

src/main.ts

import { bootstrapApplication } from '@angular/platform-browser';
import { ErrorHandler } from '@angular/core';
import { getBrowsonic } from '@browsonic/sdk';
import { provideBrowsonic, BrowsonicErrorHandler } from '@browsonic/angular';
import { AppComponent } from './app/app.component';

const sdk = getBrowsonic();
sdk.init({
  apiEndpoint: 'https://api.browsonic.com',
  appKey: 'YOUR_APP_KEY',
  apiKey: 'pk_live_YOUR_KEY',
  atlas: true, // the router instrumentation sends route templates
});

bootstrapApplication(AppComponent, {
  providers: [
    ...provideBrowsonic({ sdk }),
    { provide: ErrorHandler, useExisting: BrowsonicErrorHandler },
  ],
});

src/app/app.component.ts — navigation breadcrumbs and route templates

import { inject, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { installRouterInstrumentation } from '@browsonic/angular';

// Your root component, with its existing @Component(...) decorator.
export class AppComponent implements OnInit, OnDestroy {
  private readonly router = inject(Router);
  private stopRouter?: () => void;

  ngOnInit() {
    this.stopRouter = installRouterInstrumentation(this.router);
  }

  ngOnDestroy() {
    this.stopRouter?.();
  }
}

In an NgModule app, put the same providers in AppModule. For Angular versions before 17, use the self-hosted script described in the SDK documentation.

Remix

@browsonic/remix — Route ErrorBoundary, clientLoader and clientAction wrappers, navigation breadcrumbs.

BrowsonicRouteErrorBoundary and captureRouteError for route errors, useRemixNavigationBreadcrumbs for navigation breadcrumbs, and withBrowsonicRemixLoader and withBrowsonicRemixAction, which report errors when they run in the browser: use them to wrap clientLoader and clientAction.

Install

npm install @browsonic/sdk @browsonic/react @browsonic/remix

Quick start

app/entry.client.tsx

import { RemixBrowser } from '@remix-run/react';
import { startTransition, StrictMode } from 'react';
import { hydrateRoot } from 'react-dom/client';
import { getBrowsonic } from '@browsonic/sdk';

getBrowsonic().init({
  apiEndpoint: 'https://api.browsonic.com',
  appKey: 'YOUR_APP_KEY',
  apiKey: 'pk_live_YOUR_KEY',
});

startTransition(() => {
  hydrateRoot(
    document,
    <StrictMode>
      <RemixBrowser />
    </StrictMode>,
  );
});

app/root.tsx — or any route

import { useRouteError } from '@remix-run/react';
import { BrowsonicRouteErrorBoundary } from '@browsonic/remix';

export function ErrorBoundary() {
  return <BrowsonicRouteErrorBoundary error={useRouteError()} />;
}

Beyond the quick start

The SDK documentation covers everything that is the same in every framework: configuration, event types, the timeline, Session Replay, Web Vitals, source maps and the privacy controls. Each package's page on npm also has a README; its links to GitHub point to a private repository and do not open.