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

hazo_pay

v0.4.3

Published

Batteries-included Stripe billing for hazo apps: pricing UI, subscriptions, lifetime, coupons, dunning, refunds, invoices, tax, metering.

Readme

hazo_pay

Batteries-included Stripe billing for hazo apps — pricing UI, subscriptions, lifetime purchases, coupons, dunning/grace, refunds, invoices, tax, and metering. Stripe is the source of truth; hazo_pay keeps a webhook-synced mirror for fast rendering and feature gating.

See design/PRD.md and design/architecture.md for the full spec.

Status

Phase 3 (coupons & admin). Complete billing foundation with checkout, subscriptions, entitlements, coupons, promotion codes, refunds, invoices, tax, metering, and webhooks. Admin UI for subscriptions, customers, coupons, and refunds. See CHANGELOG.md for version history and design/PRD.md for the full product spec.

Entry points

  • hazo_pay/client — pure, browser-safe logic (no Node/Stripe): formatMoney, toMinorUnits, computeOrderTotal (discount before tax), couponDiscount, validateCoupon / effectiveMaxRedemptions, resolveEntitlement, buildPricingModel. Plus React components: PricingTable, BillingPanel, BillingAdminPanel, CouponAdminPanel, and the UpgradePromptProvider / useUpgradePrompt / UpgradePromptDialog upgrade-prompt trio (see below).
  • hazo_pay (server) — re-exports the client surface plus loadPayConfig (secrets from env) and createPayServer({ onEntitlementChange }) (the FR-15 entitlement-change seam + getEntitlement / hasActivePlan).

Test-app

A Next.js test-app demonstrates each scenario in a shadcn sidebar, with an /autotest route running the browser test suite via hazo_ui/test-harness.

npm run dev:test-app           # builds the package, then starts the test-app on :3300
PORT=3091 npm run dev:test-app # custom port

Sidebar pages: Overview, Pricing model, Entitlement, Coupons & totals, Billing panel, Admin, Webhooks, Coupons Admin, Upgrade prompt, Autotest, Live Stripe.

Upgrade prompt

UpgradePromptProvider is a headless-checkout upsell dialog: mount it once near the app root, then call useUpgradePrompt().showUpgradePrompt({ feature, requiredTier }) from anywhere beneath it to open a dialog offering monthly/yearly/lifetime price options for the gated tier. It never initiates checkout itself — you supply resolveCheckout(priceId, mode) and decide how to start the Stripe flow (redirect, server action, API call, etc.).

// app/providers.tsx
'use client';
import { UpgradePromptProvider } from 'hazo_pay/client';
import { pricingConfig } from './pricing-config';

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <UpgradePromptProvider
      pricingConfig={pricingConfig}
      resolveCheckout={async (priceId, mode) => {
        const res = await fetch('/api/checkout', {
          method: 'POST',
          body: JSON.stringify({ priceId, mode }),
        });
        const { url } = await res.json();
        window.location.href = url;
      }}
    >
      {children}
    </UpgradePromptProvider>
  );
}
// anywhere beneath the provider
'use client';
import { useUpgradePrompt } from 'hazo_pay/client';

export function BackgroundsGate() {
  const { showUpgradePrompt } = useUpgradePrompt();
  return (
    <button onClick={() => showUpgradePrompt({ feature: 'composer_backgrounds', requiredTier: 'pro' })}>
      Unlock backgrounds
    </button>
  );
}

UpgradePromptDialog (rendered internally by the provider) is theme-neutral — it's built on hazo_ui's HazoUiDialog/Button primitives and shadcn tokens (bg-primary, text-muted-foreground, …), so it inherits the consuming app's brand palette. All copy is overridable via the optional labels prop (headline, description, monthlyLabel, yearlyLabel, lifetimeLabel, savingsLabel, ctaLabel, closeLabel, noOptionsLabel).

Admin Panel

Mounting BillingAdminPanel in a Next.js page

// app/admin/billing/page.tsx
import { BillingAdminPanel } from 'hazo_pay/client';
import { createListSubscriptions, createGetCustomerDetail } from 'hazo_pay/server';

export default function BillingAdminPage() {
  return (
    <BillingAdminPanel
      getSubscriptions={createListSubscriptions({ getHazoConnect })}
      getCustomerDetail={createGetCustomerDetail({ getHazoConnect })}
      cancelSubscription={createCancelSubscription({ getHazoConnect, stripe })}
      changePlan={createChangePlan({ getHazoConnect, stripe })}
      issueRefund={createIssueRefund({ getHazoConnect, stripe })}
    />
  );
}

Wiring into hazo_admin

// admin/manifest.tsx
import { billingAdminSection } from 'hazo_pay/admin';
import { BillingAdminPanel } from 'hazo_pay/client';
// import type { AdminManifest } from 'hazo_admin/index.ui';

const manifest /* : AdminManifest */ = {
  sections: [
    billingAdminSection({
      component: <BillingAdminPanel getSubscriptions={...} ... />,
      // optional overrides:
      // path: '/admin/billing',
      // label: 'Billing',
      // permission: 'hazo_pay.admin.firm',
      // group: 'billing',
      // order: 100,
    }),
  ],
};

billingAdminSection is also available from hazo_pay/client for client bundles.

Admin API route factories

Mount these in your Next.js app/api/admin/billing/ directory:

| Factory | Import | Route | |---|---|---| | createListSubscriptionsHandler | hazo_pay/api | GET /api/admin/billing/subscriptions | | createGetCustomerDetailHandler | hazo_pay/api | GET /api/admin/billing/customers/[id] | | createCancelSubscriptionHandler | hazo_pay/api | POST /api/admin/billing/cancel | | createChangePlanHandler | hazo_pay/api | POST /api/admin/billing/change-plan | | createIssueRefundHandler | hazo_pay/api | POST /api/admin/billing/refund |

Permission strings

  • hazo_pay.admin.all — full billing admin (refunds, cancellations, plan changes)
  • hazo_pay.admin.firm — firm-scoped admin (default for billingAdminSection; cannot act on other firms' subscriptions)