Products, pricing page, checkout sessions, webhooks, and customer portal. Payments wired up so you don't have to read the Stripe docs for the 47th time.
We're about to give this template away for free — we just haven't posted the giveaway yet. Follow us on X so you don't miss it.
Follow us on XȘtefan walks you through it
Honest breakdown — no marketing fluff
Stop building payment flows from scratch.
A production-ready Next.js 16 template that handles Stripe payments so you can focus on what actually makes your product unique. One-time purchases, subscriptions, or both — configured in a single file.
You've got a great idea for a SaaS, a digital product, or a paid tool. You pick Next.js. You pick Stripe. And then you spend the next two weeks:
checkout.session.completed fires but your success page shows nothingBy the time payments work, your motivation is gone and your launch date is a memory.
We've been there. Multiple times. So we built this once — properly — and never looked back.
// payments.config.ts — that's it, that's the whole decision
const config = {
mode: "subscription", // or "one-time" or "hybrid"
customerPortal: { enabled: true },
redirects: {
success: "/checkout/success",
cancel: "/checkout/cancel",
},
}
Change mode and the entire app adapts — webhook events, UI components, checkout parameters. No hunting through 15 files to switch from subscriptions to one-time payments.
This isn't a "build a Stripe integration in 10 minutes" blog post turned into a repo. This is what we actually use. That means:
any, noUncheckedIndexedAccess enabled. Your IDE will catch bugs before your users do.strictTypeChecked — zero warnings. Not "we disabled the rules that were annoying."Nobody gets excited about error boundaries. But your users will notice when your app shows a blank white screen instead of a helpful error message.
Four event handlers with typed parameters, JSDoc comments, and TODO markers exactly where your logic goes:
onCheckoutSessionCompleted — provision access, send confirmationonInvoicePaid — extend access on renewalonSubscriptionUpdated — handle plan changes, detect cancellation intentonSubscriptionDeleted — revoke access when the period endsThe customer ID is already extracted. The subscription ID is already extracted. You just add your database call.
Next.js 16 (App Router) · TypeScript (strict) · Tailwind CSS 4 · shadcn/ui · Stripe SDK v20 · Zod · Vitest · Playwright
No experimental packages. No beta APIs. Nothing that will break in a month.
This is a payments template, not a full-stack boilerplate. It does one thing and does it well. You bring the rest.
Steps 1-3 take about 5 minutes. Step 4 depends on your business logic, not on figuring out Stripe. Step 5 is one click.
You absolutely can. And in about 20-30 hours you'll have something similar — if you remember to:
session.customer is an expanded object, not a stringreturnPath parameter against open redirect attacks@t3-oss/env-nextjs module in tests because it validates env vars at import timeoverflow-visible to the pricing card so the "Most Popular" badge doesn't get clippedsafeParse instead of parse for Zod validation in Server Actions so errors don't crash the servercancel_at_period_end in subscription updates, not just subscription deletionsx-forwarded-for with proper fallback for when there's no proxyWe already made every one of these mistakes so you don't have to.
Can I use this for just one-time payments?
Yes. Set mode: "one-time" and you're done. Subscription UI and webhook handlers are automatically disabled.
Do I need Upstash for rate limiting? No. Rate limiting is optional. Without the Upstash env vars, the app works fine — Stripe has its own API rate limits as a fallback.
Can I use pnpm/npm instead of bun?
Yes. Delete bun.lock, run your preferred install command. Nothing in the code is bun-specific.
Is this a one-time purchase or a subscription? Ironic question for a Stripe checkout template, but: one-time purchase. Buy it, own it, use it forever.
Do you provide support? Yes. We actually use this template ourselves, so any bug you find is a bug we want fixed too.
We're Robert and Stefan. We build tools for developers who'd rather ship their product than fight with payment integrations.
This template exists because we got tired of rebuilding the same Stripe setup for every new project. Now we don't. And neither do you.
Everything you need to go from zero to production.
One payment. No subscriptions, no renewals. Use it on every personal project you ever build.
Full git history, proper branches, and the ability to pull updates. The way code should be shared.
We run these in our own apps. Every edge case has been caught, every handler stress-tested.
When we improve something, you get it for free. Just pull the latest changes.
No startup hype, no investor money — just clean code we'd use in our own apps. Curious who we are? Read our story (it's fun).
Stripe Checkout Starter
Payments
Skip the 2 weeks of wiring auth, webhooks, and email from scratch. This is the exact setup we use in production — tested, typed, and ready to go.
Yours forever
One payment, no subscriptions
Full source code
Real git repo, not a zip file
Free updates
We improve it, you get it
9 commits pushed to the repo
Last updated May 5, 2026
0 open issues — yay!
“We got mass-tired of copy-pasting the same Stripe webhook handler into every new project, so we packaged it properly. This is the exact code running in our own apps — not a tutorial, not a demo. Just the thing we wished existed when we started.”
Robert, co-founder
Real people, real support. No ticket queue — you email us, we answer. Usually the same day.
We use this ourselves. Every bug fix and improvement we make for our own apps, you get for free.
No subscriptions, ever. Pay once, own it forever. We don't believe in renting code.
Built by Robert & Ștefan
Read our story (it's fun) →
We don't have thousands of customers yet — we have a handful who actually use this in production and keep coming back for more.