OneShot

← All packs

SaaS Billing + Tax Core

complex-universalverified

Production Stripe Billing core for a seat-based SaaS — plans, seats, proration, dunning, idempotent webhooks, Stripe Tax, invoices, customer portal — as a receipt-backed build pack for your own coding agent.

How install works

  • Accounts
  • Tools

Total time for this section: ~15–20 minutes, almost all of it account signups and installs, none of it billed to your Claude plan.

Full setup walkthrough ships in the zip after purchase.

Coming soon — $149
Execution receipt3 of 3 runs passed
Model
claude-sonnet-5
Run at
2026-08-02T06:37:58+00:00
Pack version
a3057f7a49c8
Tokens in / out
12,425,747 / 133,237 · per-run mean · billed input includes 11,903,065 cache reads, priced far below fresh input
Wall time
19.9 min · per-run mean
Deploy
not deployed

Acceptance checks

  • databasePASS
  • installPASS
  • prisma_generatePASS
  • contract_filesPASS
  • migratePASS
  • plan_catalogPASS
  • dunning_machinePASS
  • checkout_paramsPASS
  • proration_policyPASS
  • seats_policyPASS
  • portal_configPASS
  • webhook_signaturePASS
  • webhook_idempotencyPASS
  • routesPASS
  • buildPASS
  • typecheckPASS

Versions lock

nextjs-prisma-postgres

node24.18.1
next16.2.12
react19.2.8
react-dom19.2.8
stripe22.3.0
stripe-api-version2026-06-24.dahlia
prisma7.9.1
@prisma/client7.9.1
@prisma/adapter-pg7.9.1
typescript5.9.3
vitest4.1.10
tailwindcss4.3.3
@tailwindcss/postcss4.3.3
shadcn4.13.1
tailwind-merge3.6.0
clsx2.1.1
class-variance-authority0.7.1
@types/node24.3.0
@types/react19.2.2
@types/react-dom19.2.2
postgres17.10

Scaffold integrity

2 scaffold files modified or deleted by the buyer-agent during verification
  • package.json
  • tsconfig.json

Stripe subscription billing looks simple until you hit proration, dunning, tax registration, and webhooks that arrive late, twice, or out of order — the exact edge cases that turn a weekend project into a support-ticket generator. This pack is a receipt-verified Next.js + Prisma + Stripe billing spine — plans, seats, proration, 14-day dunning grace, idempotent webhooks, Stripe Tax, hosted invoices, and a restricted customer portal — that your own coding agent builds in a couple of sessions instead of you researching Stripe's subscription-lifecycle traps one production incident at a time. The receipt requires 16 acceptance checks to pass against a pinned stack (Node 24, Next 16, Prisma 7, Stripe API `2026-06-24.dahlia`, Postgres 17) on a named model matrix before this pack is listed — not a claim that it "always works."

Example use cases

  • **An indie B2B SaaS replacing a "charge everyone the same flat fee" MVP** with real per-seat billing (add seats now, prorated; remove seats at renewal, never mid-cycle) before it can credibly pitch a 20-seat enterprise buyer.
  • **An agency building its third or fourth client SaaS this year**, tired of re-deriving Stripe's subscription-schedule rules (one active schedule per subscription, `current_period_end`'s move onto the item object) from scratch on every engagement.
  • **A pre-launch startup whose first paying customers are EU businesses**, needing Stripe Tax's automatic calculation and B2B reverse-charge tax-ID collection correct on day one rather than bolted on after a tax authority notices.
  • **A solo developer who inherited a hand-rolled webhook handler** that silently double-charged a customer during a downgrade, and wants the replacement built on a documented idempotency and out-of-order-safety design instead of another ad hoc fix.

Why this pack

Bare agent, no packThis pack ($149 one-time)Stripe-billing SaaS platform (Chargebee/Recurly-class)Hand-rolling it yourself
**Correctness risk**High — these are exactly the bugs agents reliably ship: reading `current_period_end` off the subscription object instead of the item (broken since the `2025-03-31.basil` API move), creating a second subscription schedule for a downgrade and hitting Stripe's one-schedule-per-subscription limit, memory-based webhook dedup that silently resets on redeploy, keying the local cache by Stripe subscription id and losing a returning ("churn-and-return") customerPre-solved — each of the four is a named, tested architecture decision (D7, D10/D11, D4, D5)Low on their own platform's edge cases — but it's a black box you didn't verify, running your billing logic on their infrastructureHigh until you personally get burned by each edge case once, which is the usual way this gets learned
**Cost**Token spend plus rework every time a build fails silently$149 onceRecurring, tied to revenue — e.g. Chargebee publishes a free entry tier up to a lifetime-billing threshold, then revenue-linked fees (0.75%); higher tiers run into the hundreds per month ($599 Performance), on top of Stripe's own 2.9% + $0.30 per charge; Recurly is quote-only with a similar revenue-linked structure. Cost grows with you forever.Your own time, priced at your hourly rate, spent researching before writing the first line
**Time to correct billing**Unknown and stochastic — sometimes one-shots, sometimes silently wrong (the entire reason execution receipts exist)~2–3 agent sessions on a $20/mo plan (see `PRD.md`'s build budget)Fast to first integration, but you still hand-write the plan/seat/proration/webhook glue against *their* API — a different vendor, the same category of glue-code bugsEngineering estimate: 1–3 weeks for one developer to reach equivalent correctness, based on this pack encoding 20 non-obvious architecture decisions, each of which is normally a "found it the hard way" incident
**Lock-in**None, but also no guarantee it built the right thingNone — plain Next.js/Prisma/Stripe code you own outright; Stripe itself is the only vendor dependency, and you'd need it regardless as the payment processorReal — your proration/dunning/entitlement logic lives inside their schema and webhooks; migrating means re-implementing all of it against a new APINone, same as this pack, minus the receipt and minus the weeks of research

This pack's own receipt (published once the OneShot harness runs it) reports pass rate honestly as **M of N** verification runs on the pinned model matrix. Agent builds are stochastic; no claim here is "always one-shots."

Scale envelope

The shipped architecture is one Railway-hosted Postgres 17 instance plus one Next.js app instance, with Stripe as the system of record and the database used purely as a webhook-maintained cache (D1) of two small tables: one `Subscription` row per account, one `WebhookEvent` row per processed event (D2).

  • **What it comfortably handles:** engineering estimate, not a load-tested benchmark — on the order of **1,000–10,000 subscribing accounts**. The reasoning: writes happen only on billing *events* (checkout, plan/seat change, renewal, payment failure), not on page views or API traffic — a seat-based B2B SaaS typically generates a handful of subscription-lifecycle events per account per billing cycle. Even at 10,000 accounts averaging 3 events/month, that's roughly 30,000 short, single-row transactional writes a month (an average of one every couple of minutes, with bursts around renewal dates) — well within what a single small Postgres instance handles for this shape of write, and each webhook is one short interactive transaction (D3/D4), not a long-running job.
  • **First ceiling:** connection count on the single Postgres instance, and it shows up sooner from **customer-facing API/page traffic** (`/billing` loads, checkout/portal/invoice route calls) than from webhook volume, if you scale the Next.js app horizontally to more than one instance for that traffic. Postgres's own default is `max_connections = 100`; Prisma's own pooling guidance caps a single instance's pool around `(2 × vCPUs) + 1`, so a few app instances fit comfortably before you'd need to change anything — but it's a real, named ceiling, not an infinite one.

**Upgrade path:** a connection pooler (e.g. PgBouncer, or Railway's own pooling) in front of Postgres, then a vertical Postgres upgrade (Railway's larger Postgres plans) — no application code changes required, since D1 already treats the database as a pure cache with nothing that assumes a specific connection count.

  • **Second, later ceiling:** the webhook route processes each event synchronously inside the request handler (D3/D4) with no queue in front of it — correct for the event volumes above, since Stripe already retries failed (non-200) deliveries with its own backoff, so the app doesn't need to build retry infrastructure. If your account volume gets large enough that Stripe's own delivery-attempts view shows sustained backlog or latency, the upgrade path is to make the webhook handler acknowledge fast and enqueue the actual DB write to a background worker — Stripe's own recommendation for high-volume endpoints, and deliberately out of this pack's scope.

**What it costs to skip the pack (modelled, not measured):** building this billing spine yourself the way most people actually work — one agent on a top-tier model, no cheap-tier routing, no parallel subagents, no prompt-caching discipline — models out at roughly **$100–390 in API tokens, likely around $195**. That's this pack's own measured build volume repriced at Opus-class rates, multiplied by an exploration factor for the 20 numbered decisions in `ARCHITECTURE.md`; the pack-guided build itself measured ≈$7 of tokens per verification run (August 2026 rates), because tasks route down to cheaper tiers. Honest reading: at the likely figure that clears the $149 price, but at the low end it doesn't — treat this as roughly break-even on tokens. The reason to buy is that the four bugs named in the table above are billing bugs, and billing bugs are found by customers.

Verified against

  • claude-opus-5
  • claude-sonnet-5
  • claude-haiku-4-5

Supported stacks

  • nextjs-prisma-postgres
    node24.18.1
    next16.2.12
    react19.2.8
    react-dom19.2.8
    stripe22.3.0
    stripe-api-version2026-06-24.dahlia
    prisma7.9.1
    @prisma/client7.9.1
    @prisma/adapter-pg7.9.1
    typescript5.9.3
    vitest4.1.10
    tailwindcss4.3.3
    @tailwindcss/postcss4.3.3
    shadcn4.13.1
    tailwind-merge3.6.0
    clsx2.1.1
    class-variance-authority0.7.1
    @types/node24.3.0
    @types/react19.2.2
    @types/react-dom19.2.2
    postgres17.10

Estimated buyer token cost

660,000 tokens for one build pass (estimate, not a guarantee).

FAQ

What if the build fails?

Run `bash verify.sh` first — it prints `CHECK: <name> PASS|FAIL` per acceptance check plus the failing log tail, and `GETTING-STARTED.md` has a full failure→cause map keyed to those exact check names. If it still won't reach `VERIFY: PASS` after working through that map, that's an environment-reproducibility gap, not something to argue over in a support ticket. Full refund within 14 days of purchase if `verify.sh` fails on a supported configuration (the pinned stack and a model from the pack's matrix) — reply to your Stripe receipt email with the verify output or `FAILURE-REPORT.md` attached.

Which models and plan do I need?

Verified on `claude-opus-5`, `claude-sonnet-5`, and `claude-haiku-4-5` (the pack routes tasks across all three by difficulty). A **$20/mo plan** (Claude Pro or Cursor's equivalent model access) is enough — the PRD budgets the full build at 2–3 agent sessions, each within Claude Pro's 5-hour rolling session window; Pro's binding constraint is prompt volume against that window and its weekly cap, not raw tokens, and Anthropic doesn't publish an exact token-per-window figure, so treat the session count as an expectation, not a guarantee. Plan on **~660k fresh tokens** (input + output) for one full build, measured; the receipt separately reports ~12.4M tokens of total billed input (96% cache reads, billed near a tenth of fresh-input price) and a measured **$6.55 per verification run** — the most reliable of the three numbers.

Can I customize it after the build?

Yes. It's your code, not a hosted product. The PRD lists deliberate non-goals — trials, usage-based billing, multi-currency, a coupons UI — as things this pack doesn't build so it stays a universal spine; add them afterward. Auth is a documented one-line stub (`src/lib/account.ts`) meant to be replaced by a real auth system (see the companion `multitenant-auth-rbac` pack) without touching billing logic.

Do I own the code?

Yes, outright, no runtime license or royalty. Stripe is the only ongoing vendor dependency, and you'd need a payment processor regardless of how you built the billing layer.

Do I have to deploy on Railway?

No — you can deploy anywhere that runs Next.js and Postgres 17. Railway is prescribed because it's the stack this pack is verified and receipt-tested on (and its referral link, disclosed in `PRD.md`, is how OneShot partly funds verification); deploying elsewhere means the receipt no longer warrants your exact environment.

Is tax handled automatically?

Stripe Tax calculates and collects tax only in jurisdictions where you've added a registration in your Stripe dashboard — zero registrations means zero tax silently collected, and that liability is yours. No code can register you in a jurisdiction; it's a manual step in the live-cutover checklist, with a monthly reminder to check Stripe's own threshold-monitoring tab as you grow.

What about multi-tenant auth, free trials, or usage-based billing?

Explicitly out of scope by design (see PRD non-goals) — this pack is deliberately just the billing spine. Multi-tenant auth/RBAC is a separate companion pack; trials, metered billing, and multi-currency are extension points left open rather than built and unverified.

Why are the versions pinned so exactly (Node 24.18.1, not just "24")?

Because the receipt's warranty and the acceptance suite are both keyed to an exact, reproducible stack — a floating version range is something the receipt can't honestly verify against.

Specific problems this pack pre-solves

Prescribed services

Disclosure: some links on this page are affiliate links. We may earn a commission if you sign up through them, at no extra cost to you. We only link to services the pack actually verified against.