npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@browsonic/nextjs

v1.4.3

Published

Next.js adapter for @browsonic/sdk — App Router error pages, route-handler capture, instrumentation entry. Re-exports @browsonic/react. Apache-2.0.

Readme

@browsonic/nextjs

Next.js adapter for @browsonic/sdk — App Router error-page components (with optional pathname / params context), route-handler capture wrapper, Pages Router companions (browsonicPagesAppInit / browsonicPagesErrorInitialProps), Pages Router Atlas route templates (installPagesRouterAtlas / routeTemplateFromPathname), config wrapper, plus all the React-side primitives re-exported from @browsonic/react.

Status: current published surface — check npm or this package's package.json for the version. App Router BrowsonicErrorPage / BrowsonicGlobalErrorPage accept optional pathname + params props that consumers thread from usePathname() / useParams() and land as the nextjs.pathname tag plus a params sub-key on the consolidated nextjs context bucket. Pages Router companions ship for pages/_app.tsx (browsonicPagesAppInit) and pages/_error.tsx (browsonicPagesErrorInitialProps), and Pages Router pages can feed App Atlas their route template via installPagesRouterAtlas (see below). The instrumentation.ts helper (@browsonic/nextjs/instrumentation) ships. Build-time source-map upload is handled by @browsonic/build-tools — since 1.4.0, withBrowsonicConfig({...}, { sourceMaps: { appKey } }) registers its Webpack plugin automatically on production client builds (see next.config.js below); without the sourceMaps option the wrapper stays an exact passthrough.

Why this adapter

Next.js's App Router has framework-specific error surfaces that the React adapter alone doesn't cover:

  1. app/error.tsx is rendered by Next.js when a route subtree throws. The component is a Client Component that receives { error, reset }. We ship a drop-in for it.
  2. app/global-error.tsx owns the <html> / <body> shell and is rendered when the root layout itself crashes. We ship a drop-in for it too.
  3. app/api/.../route.ts route handlers run server-side. A wrapper forwards thrown errors to the SDK (when reachable) before re-throwing them so Next.js can serve its 500.

This package depends on @browsonic/react and re-exports its surface so Next.js consumers install one package, not two.

Install

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

@browsonic/sdk, @browsonic/react, next (≥13.4), and react (18+) are all peer dependencies.

Quickstart — App Router error pages

// app/error.tsx
'use client';
import { BrowsonicErrorPage } from '@browsonic/nextjs';
export default BrowsonicErrorPage;
// app/global-error.tsx
'use client';
import { BrowsonicGlobalErrorPage } from '@browsonic/nextjs';
export default BrowsonicGlobalErrorPage;

The components capture { error, digest } to the SDK on mount, then render a minimal "Something went wrong" UI with a Try Again button. To customise, copy the 30-line implementation from src/error-page.tsx and adjust the JSX.

To attach route-context to captured errors, wrap the default export with pathname and params from Next's hooks:

// app/error.tsx
'use client';
import { usePathname, useParams } from 'next/navigation';
import { BrowsonicErrorPage } from '@browsonic/nextjs';

export default function ErrorPage(props: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return <BrowsonicErrorPage {...props} pathname={usePathname()} params={useParams()} />;
}

The boundary tags the captured event with nextjs.pathname and lands params as a sub-key on the single consolidated nextjs context bucket (alongside runtime / source / pathname) so dashboards can group errors by route shape.

Quickstart — Pages Router (Next ≤ 12 / opt-in 13+)

For projects on the Pages Router, two companions cover the equivalent surfaces:

// pages/_app.tsx
import type { AppProps } from 'next/app';
import { useEffect } from 'react';
import { browsonicPagesAppInit } from '@browsonic/nextjs';

export default function App({ Component, pageProps }: AppProps) {
  useEffect(() => browsonicPagesAppInit(), []);
  return <Component {...pageProps} />;
}
// pages/_error.tsx
import type { NextPage } from 'next';
import { browsonicPagesErrorInitialProps } from '@browsonic/nextjs';

interface ErrorProps {
  statusCode: number;
  pagePath?: string;
}

const Error: NextPage<ErrorProps> = ({ statusCode }) => <div>Error {statusCode}</div>;

// `browsonicPagesErrorInitialProps` IS the getInitialProps: it captures the
// error (browser-side only) and returns `{ statusCode, pagePath }` synchronously.
Error.getInitialProps = browsonicPagesErrorInitialProps;

export default Error;

browsonicPagesAppInit registers window-level error / unhandledrejection listeners on the client (call it from useEffect; it returns a teardown so the listeners are removed on unmount / fast refresh) and is a no-op on the server. browsonicPagesErrorInitialProps captures whatever Next put on ctx.err, sets the consolidated nextjs context bucket (runtime: 'browser', source: 'pages-router-error', plus statusCode / pagePath / asPath when present), tags nextjs.pagePath, and records nextjsStatusCode metadata — capture only fires browser-side (it no-ops during SSR).

Quickstart — Pages Router Atlas route templates

Pages Router pages know their route template at runtime — router.pathname is the template, in Next's bracket dialect. Two helpers forward it to the SDK's page-view channel so App Atlas groups screens by parameterized route instead of raw URLs:

// pages/_app.tsx
import type { AppProps } from 'next/app';
import Router from 'next/router';
import { useEffect } from 'react';
import { installPagesRouterAtlas } from '@browsonic/nextjs';

export default function App({ Component, pageProps }: AppProps) {
  useEffect(() => installPagesRouterAtlas(Router), []);
  return <Component {...pageProps} />;
}

installPagesRouterAtlas(router) sends trackPageView(template) for the current page immediately (the initial view is exactly the page view that maps the entry screen), then again on every routeChangeComplete. It returns a teardown callback — return it from the useEffect so fast refresh never stacks listeners. Reporting failures never throw through a navigation. The router argument is a structural PagesRouterLike (pathname + events.on/off) — the default next/router singleton satisfies it, and the package takes no next/router dependency.

Pair it with the SDK init:

  • SDK ≥ 3.14: atlas: true — the core runs organic URL tracking from first paint and hands the page-view channel over on the first templated trackPageView, so there is no double counting and no extra flag.
  • Older cores: manualPageViews: true — required, otherwise the organic history-driven page view double counts every navigation.

routeTemplateFromPathname(pathname) is the underlying converter, exported for hosts that drive trackPageView themselves: Next's bracket dialect becomes Atlas's colon dialect (/users/[id]/users/:id; [...slug] / [[...slug]] catch-alls → *; other segments pass through verbatim). It returns '' for empty / non-string input so callers can fall back to the SDK's URL normalization.

App Router has no runtime route template, so these helpers are Pages Router only.

Quickstart — Route handlers

// app/api/checkout/route.ts
import { withBrowsonicRouteHandler } from '@browsonic/nextjs';

export const POST = withBrowsonicRouteHandler(async (req: Request) => {
  const data = await req.json();
  if (!data.email) throw new Error('email required');
  return Response.json({ ok: true });
});

The wrapper forwards the thrown Error to sdk.captureError, tags it with nextjsRouteHandler: 'true', and re-throws — Next.js's normal 500 path is preserved.

Quickstart — instrumentation.ts (Next 13.4+)

Next.js's project-root instrumentation.ts file convention runs once at server startup (register()) and on every unhandled server error (onRequestError). The @browsonic/nextjs/instrumentation sub-entry ships a one-line wire-up:

// instrumentation.ts (project root, alongside `next.config.mjs`)
import { browsonicInstrumentation } from '@browsonic/nextjs/instrumentation';

const { register, onRequestError } = browsonicInstrumentation({
  apiEndpoint: process.env.BROWSONIC_API_ENDPOINT,
  appKey: process.env.BROWSONIC_APP_KEY,
  environment: process.env.VERCEL_ENV ?? process.env.NODE_ENV,
});

export { register, onRequestError };

What ships today:

  • register() validates that apiEndpoint + appKey are present and emits one console.warn per missing field. Misconfiguration surfaces at server boot instead of silently shipping pages with no telemetry.
  • onRequestError(error, request, context) forwards the error to console.error with a structured nextjs.* context object (nextjs.path, nextjs.routerKind, nextjs.routePath, nextjs.routeType, etc.). Tests / custom log sinks override the report path via the reportError option.

What ships later (without a code change in your instrumentation.ts):

  • Real server-runtime capture. The SDK is a browser library today, so onRequestError forwards to console.error rather than the ingest endpoint; a server-runtime transport is future work, independent of source maps (browser-side source-map upload already ships — see below).
  • BROWSONIC_INSTRUMENTATION_VERSION already tags emitted events so future dashboards can distinguish wire-up generations.

Server-only sub-entry — the main @browsonic/nextjs bundle has no server code.

Quickstart — next.config.js

// next.config.mjs
import { withBrowsonicConfig } from '@browsonic/nextjs';

export default withBrowsonicConfig({
  reactStrictMode: true,
  // your config
});

Without options, withBrowsonicConfig is an exact passthrough — adopt it now and turn on config-level integrations later without editing this file again.

Source-map upload (auto-registration, 1.4.0+)

Pass sourceMaps and the wrapper registers the @browsonic/build-tools Webpack plugin on production client builds automatically (dev rebuilds and server bundles are skipped):

// next.config.mjs
import { withBrowsonicConfig } from '@browsonic/nextjs';

export default withBrowsonicConfig(
  {
    reactStrictMode: true,
    productionBrowserSourceMaps: true, // emit browser source maps at build time
  },
  {
    sourceMaps: { appKey: 'web' }, // any @browsonic/build-tools option, e.g. release, debugIdInjection
  },
);

@browsonic/build-tools is an optional peer — install it alongside (npm install --save-dev @browsonic/build-tools). If it is missing, the wrapper logs a warning and your build continues untouched (source-map upload is a supporting flow and must never break next build). A user-supplied webpack hook keeps working: it runs first and the plugin is appended to the config it returns.

The sourceMaps object is forwarded verbatim to BrowsonicSourceMapsPluginappKey is required; release falls back to BROWSONIC_RELEASE → git short-sha → package.json version; the upload token comes from BROWSONIC_SOURCEMAP_TOKEN; debugIdInjection: true opts into per-build debugId stamping. The release the plugin uploads under must match the SDK's clientVersion. See the @browsonic/build-tools README for every option.

Prefer wiring the Webpack plugin yourself? The manual pattern keeps working:

// next.config.mjs
import { BrowsonicSourceMapsPlugin } from '@browsonic/build-tools/webpack';

const nextConfig = {
  productionBrowserSourceMaps: true,
  webpack(config, { isServer }) {
    if (!isServer) {
      config.plugins.push(new BrowsonicSourceMapsPlugin({ appKey: 'web' }));
    }
    return config;
  },
};

export default nextConfig;

Quickstart — Boundary inside Client Components

The full React surface re-exports through this package, so anywhere in your 'use client' tree you can:

'use client';
import { BrowsonicErrorBoundary, useUser } from '@browsonic/nextjs';

export function App() {
  useUser({ id: 'u1' });
  return (
    <BrowsonicErrorBoundary fallback={(error, reset) => <div>{error.message}</div>}>
      <Routes />
    </BrowsonicErrorBoundary>
  );
}

Naming note

withBrowsonic is the React HOC (re-exported from @browsonic/react). withBrowsonicConfig is the Next.js config wrapper (this package). The split mirrors @sentry/nextjs's withSentryConfig pattern.

Defensive contract

Same as every other adapter:

  • The host app must never crash because reporting failed.
  • SDK calls are wrapped in try { ... } catch {}.
  • All surfaces work without an SDK present (page still renders, route handler still throws upstream, config still passes through).

What this package does NOT do (yet)

  • Auto-detected instrumentation.ts injection. The shipped helper is opt-in (consumer pastes a 5-line wire-up). A build-time injector that creates the file automatically would need a transform on every project's root, which is more invasive than the consumer-opt-in convention.
  • Server-runtime capture. The SDK is a browser library; route-handler errors that occur in pure Node have no window to write to. The wrapper still re-throws so your handler returns its expected status.
  • Edge runtime instrumentation. Edge runtimes lack a stable global Browsonic singleton — adopt the SDK in the client layer and use the route-handler wrapper for opportunistic capture.
  • Pages Router data layer instrumentation (getServerSideProps / getStaticProps). Will be revisited only if Pages Router consumer demand surfaces.

License

Apache-2.0. See the repo root LICENSE and the package NOTICE.