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/svelte

v1.2.17

Published

Svelte / SvelteKit adapter for @browsonic/sdk — handleError hook factory, user store subscriber, capture helpers. Apache-2.0.

Readme

@browsonic/svelte

Svelte / SvelteKit adapter for @browsonic/sdk — SvelteKit handleError hook factory, Svelte-store user-context bridge, ergonomic capture wrappers, navigation breadcrumb instrumentation, SvelteKit form-action wrapper, and a +error.svelte integration helper.

Status: published on npm — check package.json or npm for the current version (both read 1.2.13 on 2026-07-27). The 0.1 / 0.2 / 0.3 labels in AGENTS.md, the source file headers and some CHANGELOG.md entries are internal feature waves, not package versions. Pure-TypeScript helpers, no compiled .svelte files. Boundary capture relies on Svelte 5's native <svelte:boundary>. Load-bearing surfaces: SvelteKit handleError hook (generic over App.Error), Svelte store user-context bridge, navigation breadcrumb instrumentation (instrumentNavigation + trackNavigation Svelte action), SvelteKit form-action wrapper (withBrowsonicAction), and a +error.svelte page helper (reportErrorPage).

Why this adapter

Two things differentiate Svelte from the React / Vue adapters:

  1. Svelte 5 has a native <svelte:boundary>. We don't ship a competing boundary — use the framework primitive. The adapter's job is to give your onerror handler a one-liner SDK forwarder.
  2. SvelteKit's error handling is hook-driven. src/hooks.client.ts exports a handleError function that the framework calls when a load function throws or a rendered component crashes. This package gives you the factory.

Install

npm install @browsonic/sdk @browsonic/svelte

@browsonic/sdk (>=3.12.0) is a peer dependency. svelte (^4.0.0 || ^5.0.0) is a peer dependency, but the recommended target is Svelte 5 — only Svelte 5 has <svelte:boundary>.

Quickstart — SvelteKit

// src/hooks.client.ts
import { handleErrorWithBrowsonic } from '@browsonic/svelte';
import { getBrowsonic } from '@browsonic/sdk';

const sdk = getBrowsonic();
sdk.init({
  apiEndpoint: 'https://your-ingest-endpoint.test', // origin only — the SDK appends /v1/events
  appKey: 'web',
  apiKey: 'pk_live_...', // publishable key — safe to ship in the browser
});

export const handleError = handleErrorWithBrowsonic();

There is no server-side companion for hooks.server.ts. The SDK is a browser library and Browsonic publishes no Node/server runtime package — every package in this repo is browser-side. Server-runtime telemetry needs a logger of your own alongside this adapter.

Quickstart — Svelte 5 boundary

<script lang="ts">
  import { captureError } from '@browsonic/svelte';
</script>

<svelte:boundary onerror={(err, reset) => {
  captureError(err instanceof Error ? err : new Error(String(err)));
}}>
  <RiskySubtree />
  {#snippet failed(error)}
    <p>Crashed: {error.message}</p>
  {/snippet}
</svelte:boundary>

Quickstart — User identity from a Svelte store

<script lang="ts">
  import { writable } from 'svelte/store';
  import { onDestroy } from 'svelte';
  import type { UserContext } from '@browsonic/sdk';
  import { subscribeUser } from '@browsonic/svelte';

  export const user = writable<UserContext | null>(null);

  const off = subscribeUser(user);
  onDestroy(off);
</script>

Every store change is mirrored as sdk.setUser(value); setting the store to null calls sdk.clearUser().

Ordering matters. subscribeUser resolves the SDK once, at call time, and captures the result for the life of the subscription. If no SDK is reachable at that moment (the global has not been exposed yet), the subscription stays a silent no-op forever — later store changes will not retry the lookup. Call subscribeUser after sdk.init(), or pass the instance explicitly: subscribeUser(user, { sdk }). (The capture wrappers and instrumentNavigation do re-resolve on every call, so they do not have this ordering constraint.)

API

The three SvelteKit-aware captures — handleErrorWithBrowsonic, withBrowsonicAction, reportErrorPage — each also set a sveltekit context bucket (kind = handleError / action / errorPage, plus path / routeId / status when available); that bucket is what the dashboard's SvelteKit card renders. All of their tag / metadata / context writes run inside sdk.withScope(), so they ride on that one capture instead of sticking to every later event.

handleErrorWithBrowsonic(options?)

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

export const handleError = handleErrorWithBrowsonic({
  sdk, // optional; default = window.Browsonic.getBrowsonic()
  chain: (input) => ({ message: '…' }), // optional; runs after the SDK has been notified
});

Returns a SvelteKit-compatible handleError hook. Forwards the thrown value (coerced to Error) to sdk.captureError, records the URL pathname under sveltekitPath metadata, and chains into your own handler if you pass one.

subscribeUser(store, options?)

Subscribe a Svelte readable store to the SDK user context. Accepts any object with a subscribe(fn) => unsubscribe shape — Readable, Writable, custom stores. Returns the unsubscribe handle. Resolves the SDK once at call time — see the ordering note above.

captureError / captureMessage / addBreadcrumb

Ergonomic standalone wrappers that resolve the SDK from window. Use these when you don't already have a reference to the SDK in scope. All three are no-ops when the SDK is unreachable.

import { captureError, captureMessage, addBreadcrumb } from '@browsonic/svelte';

captureError(new Error('purchase failed'));
captureMessage('checkout step 2', 'info');
addBreadcrumb({ category: 'navigation', message: '/checkout' });

instrumentNavigation(options?) / trackNavigation Svelte action

Subscribe to SvelteKit / SPA navigation and emit a category: 'navigation' breadcrumb on every URL change. Two surfaces over one engine:

// Programmatic — call once at app init
import { instrumentNavigation } from '@browsonic/svelte';
const off = instrumentNavigation();
// optional: off() on app teardown
<!-- Action form — drop on a layout root -->
<script lang="ts">
  import { trackNavigation } from '@browsonic/svelte';
</script>

<div use:trackNavigation>
  <slot />
</div>

History API patches (pushState / replaceState) are ref-counted so multiple callers share one set of patches and the last unsubscribe restores the originals. Any navigation that goes through pushState / replaceState fires the synthetic browsonic:locationchange event; back/forward fire via popstate. Works without a @sveltejs/kit peer dep — the package has no dependency on it at all.

That cuts both ways: the tests drive pushState / replaceState / popstate directly, never a real goto(), so whether SvelteKit's goto() routes through the History API — and therefore emits a breadcrumb — is UNVERIFIED (2026-07-27).

withBrowsonicAction(handler, options?)

Wraps a SvelteKit actions: {} handler so unhandled throws are reported (with sveltekit.action.name / sveltekit.action.method tags + sveltekitPath metadata) and then re-thrown so SvelteKit returns the action's failure to the client unchanged.

// src/routes/login/+page.server.ts
import type { RequestEvent } from '@sveltejs/kit'; // type-only — no runtime dep
import { withBrowsonicAction } from '@browsonic/svelte';

export const actions = {
  default: withBrowsonicAction(
    async (event: RequestEvent) => {
      const data = await event.request.formData();
      // ... business logic that may throw
    },
    { actionName: 'login.default' },
  ),
};

Annotate the handler's parameter. Left unannotated, the generic falls back to this package's structural ActionEventLike shape — url.pathname, optional request.method, optional route.id, nothing else — and request.formData() fails to compile under strict.

Re-throw order matters — consuming the error here would mask every reported failure as a successful 200 response.

reportErrorPage(error, options?)

One-shot, idempotent capture for +error.svelte's <script> block. Reference-keyed de-dupe via module-scope WeakSet so a reactive $: binding doesn't re-report on every store tick.

<!-- src/routes/+error.svelte -->
<script lang="ts">
  import { page } from '$app/stores';
  import { reportErrorPage } from '@browsonic/svelte';

  $: reportErrorPage($page.error, {
    status: $page.status,
    pathname: $page.url.pathname,
  });
</script>

<h1>{$page.status}: {$page.error?.message ?? 'Something went wrong'}</h1>

Browser-only — SSR (typeof window === 'undefined') and "no SDK reachable" cases short-circuit to false so the helper is safe to call unconditionally.

resolveSdk(explicit?)

Lower-level helper for when you need explicit SDK access. Returns the explicit instance, or window.Browsonic.getBrowsonic(), or null.

Defensive contract

Every public surface follows the same rule:

  • The host app must never crash because reporting failed.
  • SDK calls are wrapped in try { ... } catch {}. If the wrapper, factory, or store subscriber can't reach the SDK, it stays silent.
  • subscribeUser returns a no-op unsubscribe when the input is not a store, instead of throwing.

What this package does NOT do

  • No <BrowsonicErrorBoundary> component. Use Svelte 5's native <svelte:boundary> and forward the thrown error from onerror via captureError. Svelte 4 has no clean boundary primitive — the SvelteKit handleError hook is the next-best mitigation.
  • Server-side capture. SvelteKit's hooks.server.ts runs in Node. The SDK is browser-only. withBrowsonicAction runs on the server too — it captures if a browser SDK is reachable (rare in pure server contexts) and otherwise re-throws cleanly.
  • No App Atlas page views. instrumentNavigation emits navigation breadcrumbs only; nothing in this package calls sdk.trackPageView(), so it feeds Atlas no route templates and no screen names. The Vue, Next.js, React and Angular adapters do; this one does not.
  • Svelte 3 / pre-Composition Svelte. Svelte 3 is end-of-life; no back-port.

License

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