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

@sepetakhq/storefront-kit

v0.1.4

Published

The non-visual half of a Sepetak storefront: API client, config, cart, checkout state, hooks and the helpers that decide what a page may say.

Readme

@sepetakhq/storefront-kit

The half of a Sepetak storefront that is not a design: the API client, the tenant config gate, the cart, checkout state, order tokens, and the helpers that decide what a page may say (sale windows, pre-order, payment kinds, shipping options, vouchers). A template imports these and owns everything visible -- screens, components, CSS, and the sentences.

npm install @sepetakhq/storefront-kit react react-dom @tanstack/react-query

Import paths

One subpath per module, the same tree the monorepo had under src/:

import { apiFetch, ApiError, configureApi } from '@sepetakhq/storefront-kit/api/client';
import { ConfigProvider, useConfig } from '@sepetakhq/storefront-kit/config/ConfigProvider';
import { CartProvider, useCart } from '@sepetakhq/storefront-kit/cart/CartProvider';
import { paymentState, MANUAL_KINDS } from '@sepetakhq/storefront-kit/lib/payment';
import { ROUTE_CONTRACT, routePaths } from '@sepetakhq/storefront-kit/shared/routes';
import { seoDevPlugin } from '@sepetakhq/storefront-kit/vite';

Rules a template lives by

  • Same origin. The client calls /api/v1 on the page's own host; the API resolves the tenant from Host. Do not call configureApi in a storefront served from the template registry.

  • The route contract. Every storefront serves exactly ROUTE_CONTRACT (/, /katalog, /produk/:slug, /keranjang, /checkout, /pesanan/:token, /track/:token, /lacak, /tentang, *). The API bakes these into emails, the sitemap and the SEO head. Pin your router:

    import { ROUTE_CONTRACT, routePaths } from '@sepetakhq/storefront-kit/shared/routes';
    expect(routePaths(router.routes)).toEqual(ROUTE_CONTRACT);
  • Branch on payment.kind, never payment.method. Render order.timeline and order.status_label, never a local table.

  • unsupported_api_version means this bundle is stale: reload the page.

  • Copy is yours. The helpers default to Indonesian and Lily Alora's colours; pass through the decision (saleState, leadDays, ...) and write your own note, the way storefront-balilinen's src/lib/copy.js does.

  • <!--seo:start--> / <!--seo:end--> stay in index.html. The API fills them per page; seoDevPlugin does the same under npm run dev.

  • /track/:token cannot be renamed. The backend composes the emailed tracking link as <origin>/track/<token> with the path hardcoded, so the route has to exist for every confirmation email already sent.

Things that will bite

  • Prices are never computed in the browser. Catalogue prices are advisory; the authoritative total appears once, in the draft response, and the server re-prices silently with no "price changed" field. The confirmation step exists so the buyer approves that total before an OTP is spent.
  • OTP is scarce: 6 digits, 5-minute TTL, 5 attempts, 5 sends per contact per hour, and a 60s → 5m → 30m resend ladder shared with order lookup. Nothing should ever send a code automatically.
  • Wrong code, expired code, too many attempts and a code bound to another checkout are one indistinguishable 400. The UI must not guess a reason.
  • track_token is returned exactly once and stored server-side only as a hash. checkout/ writes it to localStorage before anything else on success, because no endpoint — not even OTP lookup — can give it back.
  • Payment confirmation is learned only by polling /orders/track/:token. There is no push and no public payment-status endpoint.
  • A method can change kind under the storefront when the platform re-routes it; kind is derived from which payload the gateway actually returned. Order status beats payment status when they disagree, which they do: an expired order keeps a pending intent.
  • Images must stay <img> with srcset. A CSS background-image cannot use srcset at all.
  • In development make api runs the stub gateway unless real credentials are set: QRIS returns an unscannable STUB-QRIS|… payload and the payment page should show a test-mode panel rather than a QR that fails in every banking app. A real payload flows through unchanged; only the STUB- guard branches.

Publishing a storefront

sf-publish builds with Vite base set to the CDN prefix for this build and uploads dist/ to the template registry bucket, pointer last:

SF_TEMPLATE=lilyalora SF_BUCKET=sepetak-storefronts \
SF_ENDPOINT=https://<account>.r2.cloudflarestorage.com \
SF_CDN_BASE=https://cdn.sepetak.com \
AWS_ACCESS_KEY_ID=… AWS_SECRET_ACCESS_KEY=… npx sf-publish

Locally, against the dev MinIO: SF_ENDPOINT=http://localhost:9000 SF_CDN_BASE=http://localhost:9000/sepetak-storefronts with the minioadmin pair. Rollback is the pointer line alone with an older build id.

Versioning

Semver. The API is versioned by date (X-API-Version, pinned in api/client.js); a kit release that moves that pin is a minor at least.