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

v1.5.4

Published

Vue 3 adapter for @browsonic/sdk — error boundary, composables, app plugin with errorHandler chaining. Apache-2.0.

Readme

@browsonic/vue

Vue 3 adapter for @browsonic/sdk — error boundary component, composables, an app.use() plugin that chains into app.config.errorHandler, Vue Router instrumentation (breadcrumbs + Atlas route-template page views), and a Pinia integration.

Status: 1.5.x surface — check npm or this package's package.json for the current version. Boundary, four composables (useBrowsonic / useUser / useCaptureError / useBreadcrumb), plugin install, Vue Router 4 instrumentation — navigation breadcrumbs (with optional beforeEach intent phase) plus Atlas route-template page views (routeTemplateFromLocation) and the screen-name channel (routeNameFromLocation), on by default under the SDK ≥ 3.14 atlas: true umbrella — and a Pinia plugin that stamps store action errors with context. Server-side rendering capture is intentionally out of scope (browser-runtime adapter only).

Why this adapter

Vue's reconciler captures render-time and lifecycle exceptions in descendant components and routes them through errorCaptured / app.config.errorHandler. The plain @browsonic/sdk install therefore never hears about them — only the global error / unhandledrejection events. This package closes that gap.

Install

npm install @browsonic/sdk @browsonic/vue

@browsonic/sdk is a peer dependency. vue (3.3+) is a peer dependency.

Quickstart

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

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

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

Wrap the parts of your tree you want to isolate:

<BrowsonicErrorBoundary :fallback="ErrorScreen">
  <Routes />
</BrowsonicErrorBoundary>

API

browsonicPlugin

app.use(browsonicPlugin, {
  sdk, // optional; falls back to window.Browsonic.getBrowsonic()
  chainErrorHandler: true, // optional; default true — chains into app.config.errorHandler
});

Wires provide(browsonicInjectionKey, sdk) so composables can resolve via inject, and chains into app.config.errorHandler so errors that aren't caught by a boundary still reach the SDK. The previously-installed handler is preserved and called after the report.

<BrowsonicErrorBoundary>

<BrowsonicErrorBoundary :fallback="(ctx) => h('div', 'Crashed: ' + ctx.error.message)">
  <Inner />
</BrowsonicErrorBoundary>

Props:

| Prop | Type | Required | | ---------- | --------------------------------------------------- | -------- | | fallback | Component \| ((ctx: { error, reset }) => unknown) | yes | | sdk | Browsonic | no | | onError | (error: Error, info: string) => void | no |

When a child throws during render or in a lifecycle hook, the boundary forwards the error to the SDK (truncating any component stack to 1024 characters as componentStack metadata) and then renders the fallback. Returning false from errorCaptured stops further propagation.

useBrowsonic() / useUser() / useCaptureError() / useBreadcrumb()

import { useBrowsonic, useUser, useCaptureError, useBreadcrumb } from '@browsonic/vue';

const sdk = useBrowsonic();
useUser({ id: 'u1', email: '[email protected]' });

const captureError = useCaptureError();
const addBreadcrumb = useBreadcrumb();
function onClick() {
  addBreadcrumb({ category: 'ui.click', message: 'buy button' });
  try {
    risky();
  } catch (err) {
    captureError(err as Error);
  }
}

useUser accepts a plain value or a Ref (re-applies on change, immediate). All four composables are no-ops when the SDK is unreachable.

installRouterInstrumentation(router, options?)

Subscribes to a Vue Router 4 afterEach guard and emits a category: 'navigation' breadcrumb on every successful route change. Pass { includeIntent: true } to also subscribe to beforeEach and emit a phase: 'intent' breadcrumb before the navigation begins (the existing afterEach breadcrumb gets phase: 'completed'). Returns the unsubscribe handle from Vue Router for HMR-friendly teardown.

import { createRouter, createWebHistory } from 'vue-router';
import { installRouterInstrumentation } from '@browsonic/vue';

const router = createRouter({ history: createWebHistory(), routes: [...] });
const off = installRouterInstrumentation(router, { includeIntent: true });
// optional: off() during HMR teardown

Structural RouterLike shape — no vue-router runtime dep. Intent breadcrumbs are the only record of an attempted route when an error fires mid-navigation, so includeIntent: true is recommended for production observability.

Atlas route-template page views (trackPageViews). On every completed navigation the instrumentation can also drive the SDK's page-view channel with trackPageView(template, { name }) — the parameterized route template (/users/:id) that Atlas's URL normalization can never recover for alphabetic slugs, plus the host-authored screen name (see below).

  • Default (SDK ≥ 3.14): follows the core's atlas: true umbrella, feature-detected per event via Browsonic.isAtlasEnabled(). When the host initialized with atlas: true, template tracking turns on here with no second flag, and the core hands organic page views over on the first templated view — no double counting, no manualPageViews pairing. On older cores the default reads as false.
  • Explicit trackPageViews: true keeps the legacy contract on older cores — pair it with manualPageViews: true in the SDK init there, otherwise the organic history-driven page view double counts every navigation. Explicit false keeps the channel off even under atlas: true.
  • The page-view channel deliberately ignores skipInitial — that flag de-dupes breadcrumb noise, and the initial navigation is exactly the page view that maps the entry screen.

routeTemplateFromLocation(to) / routeNameFromLocation(to)

The extraction helpers the instrumentation uses, exported for hosts that drive trackPageView themselves:

  • routeTemplateFromLocation(to) — the parameterized route template from a resolved location: the deepest to.matched record's path (Vue Router stores each record's full absolute template, so no joining is needed). Returns '' when nothing matched — send undefined then, so Atlas falls back to URL normalization.
  • routeNameFromLocation(to) — the host-authored screen name: to.meta.browsonicName (explicit) or to.meta.title (the common Vue Router convention), trimmed. Returns '' when the route declares neither. Feeds the SDK's screen-name channel, so a route can name its screen from code (dashboard naming rules still override it server-side).
const routes = [
  { path: '/users/:id', component: UserProfile, meta: { browsonicName: 'User Profile' } },
];

installPiniaIntegration(pinia, options?)

Pinia plugin that hooks every store's $onAction.onError so unhandled action errors stamp the SDK scope with setContext('pinia', { storeId, action, args, errorMessage, state? }) before bubbling. The Vue boundary or window error handler then captures an event that already knows which store + action caused the failure.

import { createPinia } from 'pinia';
import { installPiniaIntegration } from '@browsonic/vue';

const pinia = createPinia();
installPiniaIntegration(pinia, {
  // Opt-in: include store state snapshot. Off by default — Pinia stores
  // commonly hold auth tokens / PII; audit per app before enabling.
  captureState: false,
  // Skip specific stores by `$id` (auth / wallet stores benefit).
  ignoreStores: ['auth'],
});
app.use(pinia);

Structural PiniaLike / PiniaStoreLike — no pinia runtime dep. maxLength (default 4096) caps serialised args / state to keep event payload size bounded.

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 boundary, plugin, or composable can't reach the SDK, it stays silent.
  • Composables and the boundary work without the plugin — they fall back to window.Browsonic.getBrowsonic().

What this package does NOT do

  • Server-side rendering capture. Out of scope. The SDK is a browser library; the adapter is a browser library.
  • Vue 2 / Options-API-only consumers. Vue 3.3+ Composition API is the contract. Vue 2 has reached end-of-life; we are not back-porting. (Note: Options API components inside a Vue 3 app are supported — the boundary catches errors from both authoring styles. The parity test suite pins this contract.)
  • Vuex state snapshot on error. Pinia is the supported store integration via installPiniaIntegration. Vuex consumers can mirror the same shape with sdk.setContext('vuex', ...) from a custom plugin, but we don't ship one.

License

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