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

@spotlight-events/storefront-js

v0.1.3

Published

Headless storefront SDK for the Spotlight embedded platform: typed availability reads and a subscribable checkout state machine over the publishable-key storefront API.

Readme

@spotlight-events/storefront-js

Headless storefront SDK for the Spotlight embedded platform. Typed availability reads and a subscribable checkout state machine over the publishable-key storefront API — the protocol's sharp edges (session-token custody, the free/paid fork, Stripe.js on the connected account, webhook-driven fulfillment, the five-minute session lifecycle) handled structurally instead of by every integration re-learning them.

  • Zero runtime dependencies. @stripe/stripe-js is an optional peer, loaded lazily only when a paid checkout proceeds.
  • ESM + CJS, Node 18+, framework-free. React binding is one line (below).
  • Wire contract shipped in the package (contract/wire-contract.json) and asserted on both sides: the backend's CI runs a spec against the live service, this package's tests assert the classifier, types, and recorded fixtures against the same file.

Install

npm install @spotlight-events/storefront-js
# paid checkout also needs the optional peer:
npm install @stripe/stripe-js

Quickstart

Everything is a subscribable store, and the flow methods are legal only in the phases they belong to — so the natural shape is: render every snapshot, act on the phases that ask for input.

import { createStorefront } from '@spotlight-events/storefront-js';

const client = createStorefront({
  publishableKey: 'spt_pk_...',                 // dashboard: Integrations -> Storefront
  apiBase: 'https://spotlight.events/api',      // the default
});

// What can a visitor do with this event right now?
const desk = client.desk(eventId);
desk.subscribe((snapshot) => {
  // { status: 'ready', mode: 'checkout', availability, actions, ... }
  // Render the ticket list; enable your buy button once
  // snapshot.status === 'ready' && snapshot.actions.checkout.
});

// From your buy button (desk is ready — checkout() throws otherwise).
// Creating a session reserves inventory for 5 minutes:
const flow = desk.checkout({
  line_items: [{ ticket_type_id, quantity: 1 }],
  buyer_email: '[email protected]',
});

flow.subscribe((s) => {
  render(s.phase);
  switch (s.phase) {
    case 'reserved':
      // Advance: free carts complete here; paid carts continue below.
      void flow.proceed();
      break;
    case 'ready_for_payment':
      // Paid only. Mount a card element from the flow's own Stripe
      // instance (non-null in this phase), then confirm from your pay
      // button:
      if (flow.stripe) {
        const card = flow.stripe.elements().create('card');
        card.mount('#card-element');
        payButton.onclick = () => void flow.confirmCardPayment({ card });
      }
      break;
    case 'completed':                     // done — s.result
    case 'charged_pending_confirmation':  // charged; never re-offer payment
    case 'payment_failed':                // recoverable; show s.error
    default:
      break;
  }
});
// After confirmation the flow polls until the fulfillment webhook lands
// -> phase 'completed'.

React

Every desk and flow is a store with a stable getSnapshot and an immediately-firing subscribe — both safe to pass unbound:

const snapshot = useSyncExternalStore(flow.subscribe, flow.getSnapshot);

Refresh survival

flow.serialize() returns a secret-bearing payload (sessionStorage is a good home); client.resumeCheckout(payload) rehydrates it. A resumed paid flow re-derives its PaymentIntent idempotently and asks Stripe for the intent status first, so an already-charged buyer is never re-shown a payable form.

Errors

Every failure is a SpotlightError: a coarse code derived purely from the HTTP status and endpoint class (never message matching), an optional fine reason, the display-safe server prose in displayMessage, and a retryable hint that is never true for mutations. reason prefers the server's machine-readable envelope code (so interpolated errors like sold-out resolve too, and the 409/410 session-expiry race collapses to session_expired); against older servers it falls back to an exact-match table over the backend's pinned copy, normalized to the same values the wire codes give — a given failure yields one stable reason regardless of server version (drifted copy degrades to undefined, never mis-classifies).

Honest limits

  • There is no client confirm endpoint; fulfillment is webhook-authoritative. On paid orders the SDK can only observe completion by polling, and charged-pending is a real outcome the partner UI must handle.
  • Tickets are never retrievable through this API. Spotlight emails them to buyer_email, valid and ready to use, with a QR code and an Apple Wallet link per ticket. On the free path result.tickets holds type-level summaries only (status completed), and a sequential retry cannot recover them. result.claimable is always false: tickets never need claiming.
  • The whole checkout must finish within 5 minutes of session creation; creating a session holds real inventory and is not retry-safe.
  • A persistent 404 can mean the platform's storefront API is disabled, not that your event id is wrong; the two are indistinguishable by design.
  • An expired result shortly after a successful charge can later become completed; never re-collect payment after a timeout.
  • Event and organization metadata (/public/*) is not part of this SDK's browser surface; fetch it server-side.
  • Origin-allowlisted keys fail closed on requests without an Origin header; server-to-server use needs a key without an origin allowlist.
  • Rate-limit headers are not readable from browser code; the documented throttle table is the contract.

Versioning

SDK 0.x tracks Spotlight API v1 at contract version 0.1.3. Breaking changes ship only in minor bumps while 0.x; additive backend evolution (new fields, new enum values) never forces a release — every wire enum is an open union. 1.0.0 is gated on the Storefront Checkout API itself shedding its feature flag.

Development

pnpm install
pnpm test          # vitest: contract, machine, http, errors, negative fixtures
pnpm typecheck     # includes the compile-time brand/open-union assertions
pnpm build         # esbuild (ESM + CJS, code-split paid module) + declarations
pnpm check:exports # attw packaging tripwire
pnpm check:size    # bundle budgets: core <= 8 kB gz, paid chunk <= +3 kB
pnpm test:smoke    # live free-path smoke vs the seeded dev storefront (env-gated)

Releases are managed with changesets: pnpm changeset to record a change, pnpm changeset version to cut the version.