Ship your SaaS this month,
not next quarter.

A Next.js 15 SaaS boilerplate with auth, Stripe billing, teams with enforced seats, hashed API keys and an admin panel — plus the one thing no other kit ships: a command that audits its own claims before you believe a word of this page.

One-time payment · lifetime updates · 30 days to change your mind, no questions asked

No testimonial wall, because nobody’s face proves a codebase. The demo is open, and the audit runs on your machine.

Week one, every single time

You are about to rebuild the same fortnight.

None of it is your product. All of it stands between you and the first customer who hands you money.

The arithmetic

Priced in the only currency you actually spend

An honest estimate of the hours behind each part, written by the person who wrote them. Every line is code you can open in the demo — or count with npm run audit once it is yours.

Auth, middleware, protected routes, user sync8 h
Stripe checkout, portal, webhooks, plan gating14 h
Teams: organizations, roles, invitations, enforced seats16 h
Hashed API keys, rate limit, reference endpoint6 h
Admin panel: users, MRR, churn8 h
8 languages across the app, ICU plurals, parity tests20 h
Five transactional emails, previewable5 h
Seven themes, dark mode, shadcn token contract6 h
MDX blog, sitemap, hreflang, OG, JSON-LD7 h
136 tests on the parts that cost money when they break10 h
Your week one, done properly100 hours

An estimate, not an invoice — your hours may be faster. Put your own rate on them anyway.

100 hours → $149, once. The rest of the month goes into the part nobody else can build for you.

Get SaaS Starter — $149
Codebase Auth Payments Teams Activity API keys Languages Themes Admin The audit
Codebase

A repository your agent can read

One Next.js 15 app, App Router, server components, TypeScript strict. A CLAUDE.md that documents the actual patterns — not a summary of the README — plus Cursor and Copilot instruction files, so your assistant knows the conventions from the first prompt instead of inventing new ones.

  • CLAUDE.md, .cursorrules, Copilot
  • End-to-end type safety
  • 25 routes, 110 files, no monorepo
  • Prompts library in docs/
src/
app/
(marketing)/ landing, pricing, blog
dashboard/ protected app
settings/ profile + API keys
billing/ plan, portal, invoices
organization/ members, roles, invites
admin/ users, metrics, MRR
invite/[token]/ accept an invitation
api/ webhooks, stripe, v1/me
lib/
organizations.ts roles, seats, invites
api-keys.ts hash, verify, revoke
stripe.ts PLANS, limits, checkout
messages/ en fr de es it nl pl pt
__tests__/ 136 tests, Vitest
Authentication

Sign-in you don't have to think about

Clerk handles sessions, social login, SSO and the password reset flow you would otherwise write twice. What the kit adds is the part that is actually yours: middleware that protects every locale of every private route, and server helpers that fail closed.

  • Social login & SSO
  • requireUser / requireAdmin
  • Locale-aware route protection
  • Webhook user sync + first-admin bootstrap
/sign-in

Welcome back

Sign in to continue to Acme.

ada@example.com
••••••••••
Sign in
or
Continue with GitHub
Payments

Charge on day one, not sprint three

Three plans configured, monthly and yearly. Checkout, the customer portal, and the four webhook events that actually matter — including the subscription-deleted case most kits forget, which is how a churned customer keeps their paid plan forever.

  • Checkout + billing portal
  • Signature-verified webhooks
  • Plan limits enforced in code
  • Cancellation downgrades the plan
/dashboard/billing

Current plan

Renews on 1 October 2026

ProActive
// src/lib/stripe.ts pro: { price: { monthly: 29, yearly: 290 }, limits: { projects: 10, apiCalls: 10000, seats: 5 }, }
Manage subscription
Change plan
Organizations

Teams, with seats that actually hold

Workspaces, OWNER › ADMIN › MEMBER re-checked in the database on every mutation, and email invitations tied to one address. Seats come from the plan and are enforced: a pending invitation holds a seat, so a free workspace can't invite twenty people and discover the limit when they all accept.

  • Invite, revoke, change role, leave
  • The last owner can't be removed
  • One subscription covers the team
  • Invite links are noindex & POST-only
/dashboard/organization
4 of 5 seats used Pro

3 members · 1 pending invitation

MemberRole
ALAda Lovelaceada@acme.com
Owner
GHGrace Hoppergrace@acme.com
Admin
ATAlan Turingalan@acme.com
Member
?katherine@acme.comInvite expires in 6 days
Invited
Activity log · new in October

Who removed Bob? Now you can answer.

Every invite, join, role change, removal, rename, API key and plan change lands in an append-only audit trail per workspace. Admins read it on the dashboard, export it to CSV for the auditor, or pipe it into Slack and their SIEM through the API — the thing enterprise buyers ask about on the second call.

  • Append-only, written after the action succeeds
  • Snapshots: deleting a user never rewrites history
  • CSV export, formula injection neutralised
  • GET /api/v1/activity, cursor-paged
/dashboard/organization#activity
Activity logExport CSV
  1. ada@acme.com invited katherine@acme.com as Admin

    2 min ago · member.invited

  2. grace@acme.com changed the role of alan@acme.com: Member → Admin

    1 h ago · member.role_changed

  3. ada@acme.com changed the plan from FREE to PRO

    yesterday · billing.plan_changed

  4. alan@acme.com created the API key ci-deploy (sk_live_7f3a…)

    2 days ago · api_key.created

API keys

Machine access, hashed at rest

A key is shown once and stored only as a SHA-256 — a dump of the table grants nobody anything. Keys are gated on the plans that advertise API access, read straight off the same PLANS object your pricing page renders, so the table and the gate can't drift apart.

  • Create, reveal once, revoke
  • Bearer or x-api-key
  • Rate limited per key, not per IP
  • A working endpoint to copy
/dashboard/settings — API keys
Production serversk_live_7Ka9Xf••••••••••••
Last used today
CI pipelinesk_live_Qm2Vd0••••••••••••
Never used
$ curl https://acme.com/api/v1/me \ -H "Authorization: Bearer sk_live_…" { "email": "ada@acme.com", "plan": "PRO", "key": { "name": "Production server" } }
Internationalization

Eight languages — inside the app, too

Most kits translate the landing page and stop at the login wall. Here the whole signed-in product is localized: dashboard, settings, billing, admin, teams, API keys. Dates, numbers and currency follow the request locale instead of a hard-coded one.

  • next-intl, ICU plurals
  • hreflang + per-locale sitemap
  • Default locale unprefixed
  • A test that fails on drift
src/messages/*.json
ENFRDEES ITNLPLPT

app.organization.seatsUsed

en4 of 5 seats used
fr4 sièges utilisés sur 5
de4 von 5 Plätzen belegt
plZajęte miejsca: 4 z 5
✓ npm test fails if one locale drifts — a missing key, an empty value, or a different ICU placeholder.
Themes

Seven looks, one variable

Not seven hues — seven complete themes. Each redefines the whole token set for light and dark, corner radius included, so they read as different products rather than the same one tinted. Nothing in a component names a colour, which is why NEXT_PUBLIC_THEME can change all of it.

  • Default, Ink, Paper, Mono, Violet, Sunset, Forest
  • Light and dark, both complete
  • shadcn registry components inherit them
  • A test fails on a half-applied theme
Try all seven, live
src/styles/themes.css

default

ink

paper

mono

violet

sunset

forest

yours
+1 block
# .env NEXT_PUBLIC_THEME="forest" # the dashboard, the admin area, the marketing pages and every # component you add later from the registry all follow.
Admin

Know your numbers from day one

A real admin area, not a placeholder: every user, their plan and role, estimated MRR, active subscriptions, churn and new signups this month — computed from your own database, with no third-party dashboard to wire up first.

  • Users, plans, roles
  • MRR & churn estimates
  • Role-gated by middleware
  • First admin from an env var
/admin
Total users1,247+8.2%
Active subscriptions318+12.4%
Estimated MRR$12,470+23.1%
Churn2.1%−0.3%
UserPlanSigned up
ALAda Lovelaceada@acme.com
Business2 September 2026
GHGrace Hoppergrace@acme.com
Pro31 August 2026
ATAlan Turingalan@acme.com
Free30 August 2026

And the rest

The parts nobody wants to write twice

Every one of these is wired and queried. None of them is a model sitting in an empty table waiting for you to finish it.

Transactional email

Resend + React Email. Welcome, subscription active, payment failed, magic link, team invitation — five real templates, previewable with npm run email:dev.

MDX blog

Frontmatter, tags, drafts, full metadata, and posts in the sitemap. Content SEO you can start on the day you launch, not the quarter after.

SEO out of the box

Dynamic sitemap with every locale, robots.txt, canonical URLs, hreflang, Open Graph and Twitter cards, JSON-LD. Discoverable from the first deploy.

136 tests, Vitest

Role hierarchy, seat maths, key hashing, webhook signatures, plan gating, locale parity. Written to catch the mistakes that cost money, not to pad a number.

Dark mode, natively

CSS variables on the shadcn/ui token contract, so npx shadcn add drops components in already themed. System-aware with a manual toggle.

Deploy anywhere

Vercel in three clicks, or the included Dockerfile and docker-compose for your own box. No proprietary runtime, no platform lock-in, no phone-home.


The differentiator

A codebase that reports its own gaps

Every boilerplate landing page is a list of claims. This one ships the command that checks them — and it was built to fail, out loud, when the code and the promise disagree.

npm run audit — an earlier commit of this repo
6 findings • Model ApiKey is declared in schema.prisma but prisma.apiKey is never called in src/. It ships as an empty table. • NEXT_PUBLIC_GA_ID is read by the code but missing from .env.example. • ADMIN_USER_IDS is declared in .env.example but never read. … These are gaps between what the code declares and what it runs. Fix them, or delete the declaration — a fork you can't trust is worse than no fork.

That was real output from this repository. So the API keys got built, the env vars got wired, and the audit was run again:

npm run audit — today
$ npm run audit Size src/app 43 files 2571 code src/components 29 files 2048 code src/lib 12 files 1111 code src/__tests__ 12 files 762 code ──────────────────────────────────────────────── total 110 files 7057 code Data model (uses = calls to the Prisma client in src/) User 16 fields 30 uses Organization 9 fields 3 uses Membership 7 fields 10 uses Invitation 11 fields 8 uses ApiKey 10 fields 5 uses ActivityEvent 9 fields 1 uses WaitlistEntry 3 fields 1 uses Locales (8 declared · 391 keys in en) en fr de es it nl pl pt complete No findings. Every model is queried, every env var is wired.

It runs on your fork too

Delete the blog, drop the admin panel, strip a plan — then run it again. It names what you left dangling.

It fits in CI

npm run audit -- --strict exits 1 on any finding. --json gives a script the same data.

It is not marketing

It reads the files on disk: sizes, routes, models with how many times the code queries them, env vars cross-checked against .env.example.


Compare

Where this kit fits — and where it doesn't

A comparison you can check. Every competitor cell below is what their own site said on 1 September 2026; the links go straight to them. Where we are behind, the table says so — you are going to open both tabs anyway.

SaaS Starter supastarter ShipFast
Price (single dev)$149 once€299 once$199 once
ShapeOne Next.js 15 appMonorepo, several appsOne Next.js app
AuthClerkbetter-auth (self-hosted)Google OAuth & magic links
PaymentsStripeStripe, Lemon Squeezy, Polar, Creem, DodoStripe, Lemon Squeezy
DatabasePrisma + PostgreSQLPrisma or DrizzleMongoDB or Supabase
Teams & rolesYes, with enforced seatsYesNot advertised
API keysYes, hashed + endpointNot advertisedNot advertised
Languages8, app includedYesNot advertised
Admin panelUsers, MRR, churnSaaS Admin UINot advertised
Tests shipped136 unit tests (Vitest)Playwright E2E configuredNot advertised
Self-audit commandnpm run auditNoNo
Background jobs, S3, notificationsNot includedIncludedNot advertised
Error monitoring (Sentry)Not includedIncludedNot advertised

The honest summary: supastarter is a larger kit — a monorepo with modules this one does not have, at twice the price. If you need file storage, background jobs and Sentry pre-wired, buy that. This kit is one app you can read in an afternoon, where every claim on this page is checkable by a command in the repo. That is the trade.

More angles, at length: the 2026 comparison of Next.js SaaS starter kits, the template walkthrough with the real repo tree, free & open-source options and what "free" costs, Clerk + Prisma vs Supabase, and what buying a kit costs you in shadcn registry compatibility.


Pricing

Pay once. Ship forever.

No subscription, no seat count, no licence key phoning home. You get the repository, and the hundred hours above back.

One-time payment — not a subscription 30-day refund — no questions asked

Starter

For your own product.

$149

One-time · lifetime updates

  • Full source, MIT-style license for one product
  • Every module on this page
  • All 8 language files
  • Docs, prompts library, setup CLI
  • Lifetime updates
Get Starter — $149

Secure checkout by Stripe · repository access in minutes

Unlimited

Best value

For agencies and serial builders.

$299

One-time · lifetime updates

  • Everything in Starter
  • Unlimited products, yours or your clients'
  • White-label — no attribution required
  • Priority email support
  • Lifetime updates
Get Unlimited — $299

Secure checkout by Stripe · repository access in minutes

Not sure? Open the live demo and click through the dashboard, the billing page and the team screen before you decide.


FAQ

Questions people actually ask

What exactly do I get?
A private Git repository: 110 files, ~7,060 lines of code, 25 routes, 136 tests, 8 locale files, the docs and the prompts library. No runtime service of ours, no licence key phoning home — clone it and it is yours.
Do I have to use Clerk, Stripe and Resend?
No, but the kit is wired for them. Auth touches lib/auth.ts and the middleware; payments live in lib/stripe.ts plus two API routes; email is one file. Swapping any of the three is a contained job, not a rewrite — and the audit will tell you if you leave something half-connected.
Is the whole app really translated, or just the landing page?
The whole app. Dashboard, settings, billing, admin, teams and API keys are all in the app namespace of the eight message files, with ICU plurals and locale-aware dates and currency. A test suite fails the build if a locale drifts — that is the part most kits skip.
How are teams billed?
Billing stays on the person who pays. A workspace's plan is its owner's plan, so one Stripe subscription covers the team and your checkout flow is unchanged. Seats come from PLANS[...].limits.seats and are enforced when an invitation is created and when it is accepted.
Can my AI assistant work with this?
That is what CLAUDE.md, .cursorrules and the Copilot instructions are for. They document the real patterns — where auth guards go, how plans gate features, why the components are shadcn-compatible without being shadcn-generated — so your assistant extends the codebase instead of inventing a second style beside it.
What is not in the box?
Background jobs, S3 file storage, in-app notifications and Sentry are not included. Neither is a monorepo. If those are requirements today, the comparison above points you at the kit that has them. This one is deliberately one readable app.
Do I get updates?
Yes, for life, on both licences. You keep repository access and pull whatever you want. Nothing is pushed into your fork.
Can I get a refund?
Yes. Thirty days, no questions asked. Email the address you paid with and the purchase date — you do not have to give a reason. The refund goes back to your original payment method within five business days, and repository access is revoked. That is the entire refund policy: it has no cases and no exceptions.

Why this exists

I got tired of buying claims.

Every boilerplate landing page is a list of promises, and you only find out which ones were true after you have paid and cloned. Half-finished models. A table declared in the schema and never queried. An env var in .env.example that nothing reads. You inherit them quietly, and you pay for them three weeks later.

So this kit ships the command I wanted as a buyer: npm run audit. It reads the files on disk and names every gap between what the code declares and what it runs. It found six in this repository, and they got fixed — that terminal output is further up this page, failures included.

That is the whole deal. Not “trust me” — “check me, here is the command.” It runs on your fork too, the day you delete something and want to know what you left dangling.

— the developer who maintains this repository

Start on Monday with week one already done

Auth, billing, teams, API keys, admin, emails, eight languages — and the command that proves every word of it. Thirty days to change your mind.