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

@fixback/sdk

v0.2.0

Published

The Fixback capture SDK — a boot-gated, self-isolating on-page feedback launcher.

Readme

@fixback/sdk

The Fixback capture SDK — a tiny, self-isolating on-page feedback widget.

init({ key }) asks Fixback whether a submission would be accepted for your publishable key, the visitor's origin, and the Project's Gate, and mounts a launcher only when it would. Nothing renders when the origin isn't allowlisted or the Gate turns the visitor away, and if Fixback can't be reached the SDK stays completely silent — it never throws into the host page.

Activating the launcher opens the report overlay: the Reporter picks a Kind (bug / improve / idea), writes a comment, optionally points at the element they mean, and hits Send — which captures a masked screenshot of the current view, assembles the annotation, and submits it to Fixback. A successful send shows a confirmation; a refusal or an unreachable Fixback fails quietly, leaving the host page untouched.

  • MIT-licensed and dependency-free.
  • Isolated styles — the launcher and overlay each live in a Shadow DOM, so the host page's CSS can't reach in and the SDK's CSS can't leak out.
  • Private by default — input values are masked before the screenshot is captured, so private text never leaves the page.
  • Two builds — an ESM entry for bundlers and a single minified <script> file for no-build sites.

Install

npm install @fixback/sdk

With a bundler (ESM)

import { init } from "@fixback/sdk";

init({ key: "pk_live_your_publishable_key" });

No build step (<script> tag)

The minified UMD build is served from any npm CDN and exposes a Fixback global:

<script src="https://unpkg.com/@fixback/sdk"></script>
<script>
  Fixback.init({ key: "pk_live_your_publishable_key" });
</script>

Options

init(options) returns a promise that resolves to an instance with a destroy() method. All options other than key are optional.

| Option | Type | Default | Description | | ---------------- | ------------- | -------------------------- | ----------------------------------------------------------------------- | | key | string | — | Your Project's publishable key (an identifier, not a secret). | | apiUrl | string | https://api.fixback.dev | The Fixback API origin. Override for a self-hosted or local deployment. | | signedIdentity | string | — | A Signed-identity token minted by your server, for trusted reporters. | | reporterId | string | — | The handle returned when a reporter redeems an invite. | | anonymousId | string | a persisted per-browser id | A stable first-party id for an anonymous reporter. | | target | HTMLElement | document.body | Where to mount the launcher. | | reduceMotion | boolean | false | Still the launcher's pulse and motion (see The launcher). | | autoCapture | boolean | true | Automatic error capture — file uncaught errors with no prompt (see Automatic error capture). Set false to turn it off. |

None of the identity fields is a trust tier — Fixback derives trust on the server and never honours a self-declared tier.

const fixback = await init({ key: "pk_live_..." });
// later, to tear the launcher down:
fixback.destroy();

The launcher

The launcher is a bottom-right Feedback pill, and it stays out of the way:

  • Hover-peek & tuck-away — the pill's caret tucks it off-screen behind a small edge nub. Hovering the bottom-right corner (or the nub) peeks it back; clicking the nub — or pressing Enter/Space on it — brings it fully back, which also covers pointers that can't hover (touch, keyboard). A brief hint appears the first time it's tucked, pointing at the corner.
  • First-visit welcome — a one-time toast greets a new visitor, drawing the eye with a gentle pulse. It shows once per publishable key per browser.
  • Reduce motion — pass reduceMotion: true to still the pulse and the slide/fade transitions. The launcher also honours the visitor's OS-level prefers-reduced-motion: reduce on its own, with no configuration.

All of this chrome lives inside the launcher's Shadow DOM, so it never adds a global style or touches the host page's markup.

The launch event

Activating the launcher opens the SDK's own report overlay. It also dispatches a composed, bubbling fixback:launch event from the SDK's host element, so the host page can react to it too:

import { LAUNCH_EVENT } from "@fixback/sdk";

document.addEventListener(LAUNCH_EVENT, () => {
  // the report overlay is opening — react here if you need to
});

Automatic error capture

The SDK's signature capability: errors report themselves, with no prompt. Two capture-phase global handlers (error + unhandledrejection) turn uncaught exceptions and unhandled promise rejections into source: auto, Kind = bug Feedback for the current session's reporter — carrying the same masked screenshot and trace buffer a manual report does, plus a per-session fingerprint. It is on by default across every Gate; pass autoCapture: false to turn it off.

  • Deduped & rate-limited. The same error reported many times collapses to one Feedback with a rising occurrence count. A token-bucket burst limiter and a per-session cap keep a runaway error loop from flooding the queue; the excess is dropped and kept only as a local count. On a 429 + Retry-After from ingest, auto-reporting backs off until the window clears.
  • Gated like a manual report. Auto-capture only runs where a submission would be accepted (boot's canSubmit), so a public visitor's crash is tracked at their server-derived tier — never auto-shipped. console.error is not promoted to a report; it stays breadcrumb-only Evidence.
  • Private-by-default. Every auto-report passes through the same client-side beforeSend scrub choke point as a manual one — input values and request/response bodies never leave the browser, and your hook can drop an auto-report entirely.

Invite redemption

An invited tester needs no account and no setup. When a page loads with an invite token in its URL (?fixback_invite=<token>), init reads the invite's status and renders the SDK's own onboarding modal — the site you were invited to, the access tier the redemption grants (server-derived, never guessed on the client), a private-by-default note, and a "Continue as" name / email:

init({ key: "pk_live_..." }); // auto-detects ?fixback_invite= on the page

On confirm the SDK redeems the invite, persists the returned reporterId in localStorage (scoped to your publishable key), strips the token from the URL (one-time consumption), and mounts the launcher. On later visits init presents that stored reporterId, so a returning tester is recognised at their correct tier without re-onboarding — and on an Invited or Internal Gate the launcher appears only after redemption, while an Open Gate shows it to anyone.

The name / email are self-provided display fields — never a trust signal; the tier is always the server's to derive. If the token reaches the page some way other than the URL, redeem it explicitly:

import { redeem } from "@fixback/sdk";

redeem({ key: "pk_live_...", token: "the-invite-token" });

How the boot gate works

On init, the SDK POSTs to ${apiUrl}/api/ingest/boot with your key (the browser attaches the Origin header itself). The server answers with canSubmit, and the launcher is mounted only when that is true. Any non-answer — an unreachable API, a refused key, an unexpected error — is treated as "don't show the launcher", silently.

Development

pnpm --filter @fixback/sdk test        # DOM tests (jsdom)
pnpm --filter @fixback/sdk build       # dist/index.mjs + dist/fixback.umd.js + types

examples/index.html is a minimal page that loads the built UMD file and calls Fixback.init — run the build first, then open it in a browser.

License

MIT — see LICENSE.