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

@pyrx/synapse-browser

v0.4.0

Published

PYRX Synapse Browser Tracking SDK — lightweight client-side event tracking, Web Push (VAPID), In-App Messaging, and the optional in-app UI Kit (@pyrx/synapse-browser/ui)

Readme

Synapse CEP — JavaScript Tracking + Web Push SDK

Lightweight client-side SDK for tracking user events and (Phase 9.1+) subscribing browsers to Web Push notifications in the Synapse Customer Engagement Platform.

Size: ~22 KB minified (event tracking + Web Push surface)

Browser support (Web Push, Phase 9.1): Chrome ≥ 50, Firefox ≥ 44, Edge ≥ 17, Safari macOS ≥ 16. iOS Safari requires a PWA install + iOS 16.4+ — verification deferred to a 9.1.x follow-up.

Installation

Script Tag (recommended)

<!-- Synapse Tracking SDK -->
<script>
  !(function () {
    var s = (window.synapse =
      window.synapse ||
      function () {
        (s.q = s.q || []).push(arguments);
      });
    var e = document.createElement("script");
    e.type = "text/javascript";
    e.async = true;
    e.src = "https://synapse-events.pyrx.tech/sdk/v1/synapse.min.js";
    var x = document.getElementsByTagName("script")[0];
    x.parentNode.insertBefore(e, x);
  })();

  synapse("init", { apiKey: "psk_prod_YOUR_API_KEY" });
  synapse("page");
</script>

npm (for bundlers)

pnpm add @pyrx-crm/sdk
import { synapse } from "@pyrx-crm/sdk";

synapse("init", { apiKey: "psk_prod_YOUR_API_KEY" });

Usage

Identify Users

Call after login to associate events with a known user:

synapse("identify", "user-123", {
  email: "[email protected]",
  first_name: "Jane",
  last_name: "Doe",
  plan: "pro",
});

Track Events

synapse("track", "cart.abandoned", {
  product: "Widget",
  price: 29.99,
  currency: "USD",
});

synapse("track", "feature.used", {
  feature: "export_csv",
  rows: 1500,
});

Page Views

// Automatically captures URL, path, title, referrer
synapse("page");

// With custom properties
synapse("page", { section: "pricing" });

Reset (on logout)

synapse("reset");

Web Push (Phase 9.1)

Five new commands on the same facade subscribe a browser to Web Push and manage the subscription. The full setup guide ships in PR-3 — what follows is the SDK-side API surface.

Prerequisites

  1. Generate a VAPID credential in Dashboard → Settings → Push Credentials → VAPID (PR-3 surface). Copy the public key.
  2. Copy node_modules/@pyrx/synapse-browser/dist/synapse-sw.js to your site's public directory (PR-3 ships the file). Add to postinstall if you want automatic updates:
    {
      "scripts": {
        "postinstall": "cp node_modules/@pyrx/synapse-browser/dist/synapse-sw.js public/synapse-sw.js"
      }
    }
  3. Call synapse('identify', userId) before subscribing — Web Push requires an identified user so the backend can associate the device with a contact.

enablePush — register the SW + prepare state

Safe to call from any lifecycle hook (no user gesture required):

synapse("enablePush", {
  vapidPublicKey: "BPV9...", // from the dashboard
  serviceWorkerPath: "/synapse-sw.js", // default
  serviceWorkerScope: "/", // default
});

On browsers without Service Worker / PushManager / Notification support (e.g. private windows, Safari iOS without PWA install), the call logs a one-line warning and resolves cleanly — your code never crashes.

requestPermission — show the permission prompt + subscribe

Must be called from a user gesture handler (click, tap). Browsers silently deny otherwise.

button.addEventListener("click", async () => {
  try {
    const subscription = await synapse("requestPermission");
    console.log("Subscribed:", subscription.endpoint);
  } catch (err) {
    if (err.code === "permission_denied") {
      // User said no — show your own UI rationale.
    }
  }
});

disablePush — unsubscribe + delete device server-side

synapse("disablePush");

Idempotent. Always succeeds locally even if the backend DELETE fails.

getSubscription — inspect current state

const sub = await synapse("getSubscription");
// → { endpoint, p256dh, auth, permission, deviceId } | null

setPushPreferences — per-device preferences

synapse("setPushPreferences", {
  quiet_hours: "22:00-07:00",
  mute_channels: ["promo"],
});

Stored on the backend devices.metadata JSONB column — schema is tenant-defined.

Error types (TypeScript)

import {
  SynapsePushUnsupportedError,
  SynapsePermissionDeniedError,
  SynapsePushNotEnabledError,
  SynapseUserNotIdentifiedError,
  SynapseServiceWorkerError,
  SynapseDeviceRegistrationError,
} from "@pyrx/synapse-browser";

Every push error has a stable .code string (push_unsupported, permission_denied, etc.) safe to switch on.

In-App UI Kit (@pyrx/synapse-browser/ui)

The core SDK delivers in-app messages to a rendering callback and does not draw UI — your app owns the pixels (see synapse('inApp.show', ...)). If you just want a sensible default, the optional UI Kit ships pre-built, themeable modal + banner renderers. It's a separate subpath export, so if you don't import it, it adds zero bytes to your bundle (tree-shaken).

5-line integration

import { synapse } from "@pyrx/synapse-browser";
import { attachUIKit } from "@pyrx/synapse-browser/ui";

synapse("init", { apiKey: "psk_prod_xxx" });
synapse("identify", "user-123");
attachUIKit(synapse, { placement: "home_modal", layout: "modal" });

attachUIKit registers an inApp.show callback that renders every fresh message on placement with the chosen layout ('modal' or 'banner'), wired to the SDK's dismiss + CTA telemetry automatically. It returns the SDK's unregister function.

Direct render (full control)

Call the renderers yourself inside your own inApp.show callback:

import { renderModal, renderBanner } from "@pyrx/synapse-browser/ui";

synapse("inApp.show", "home_modal", (message) => {
  const handle = renderModal(message, {
    theme: { accent: "#7c3aed" }, // optional --pyrx-ui-* overrides
    onDismiss: (id, reason) => {
      /* … */
    }, // optional; defaults to the SDK
    onCtaClick: (id, ctaId) => {
      /* … */
    }, // optional; defaults to the SDK
  });
  // handle.element — the mounted root; handle.close() — remove it.
});

Theming

The kit is self-contained (no web fonts, no CDN, no external assets) and namespaces every style under .pyrx-ui, so it won't collide with your site. Re-theme via options.theme (per-instance) or by setting --pyrx-ui-* CSS variables globally. Overridable tokens: accent, accentHover, accentForeground, surface, foreground, foregroundMuted, border, backdrop, radius, fontFamily, zIndex. Default accent is the PYRX teal #1d9e75.

Accessibility & security

  • Modal: role="dialog" + aria-modal, focus trap, Escape-to-dismiss, backdrop-click-to-dismiss, focus restored on close.
  • Banner: role="status", non-blocking (no focus trap, no Escape).
  • All message text is rendered via textContent (never innerHTML), and every URL sink (image src, CTA navigation) is funnelled through one strict http(s)/relative-only sanitizer — a javascript: / data: URL in tenant-authored content can never execute on your origin.

The kit is desktop-first but ships responsive CSS since it embeds in arbitrary sites. Scope: modal + banner (tooltip / carousel / inbox are not included).

Configuration

synapse("init", {
  apiKey: "psk_prod_xxx", // Required
  endpoint: "https://synapse-events.pyrx.tech", // Default
  flushInterval: 5000, // ms between flushes (default: 5s)
  flushSize: 10, // events before auto-flush (default: 10)
  debug: false, // Console logging (default: false)
});

How It Works

  1. Events are queued in memory and persisted to localStorage
  2. Queue flushes every 5 seconds or when 10 events accumulate
  3. Events are sent as a batch to POST /v1/events/batch
  4. On page unload, sendBeacon ensures delivery
  5. Failed flushes retry with exponential backoff (1s, 2s, 4s)
  6. Queue survives page refreshes via localStorage