Run all your apps from one project.
Millroom is a Next.js and Supabase codebase for people who ship more than one app. Each app gets its own domain and brand; all of them share one deploy, one database and one set of accounts. Set up auth, billing, email and analytics once, and every app you add inherits them.
Bought once on Gumroad. No subscription, no per-app fee, unlimited apps.
A cut plan: one sheet, three apps as parts, one part still to be cut, and an offcut.
What six apps cost you before the first user.
Take six apps, built the usual way. Each one wants its own project at every vendor before it has a user, and none of it is hard, which is why you keep agreeing to it. On millroom there is one of each, and all six run inside them.
| what you set up | six apps, six repos | six apps on millroom |
|---|---|---|
| Vercel projects | 6 | 1 |
| Supabase projects | 6 | 1 |
| Stripe accounts | 6 | 1 |
| Stripe webhook endpoints and signing secrets | 6 | 1 |
| Google consent screens to verify | 6 | 1 |
| Resend accounts | 6 | 1 |
| Sending domains to verify | 6 | 6each app still verifies its own |
| PostHog projects | 6 | 1 |
| Sitemap and robots routes | 6 | 1 |
| Privacy, terms and licence copy | 6sets | 1shared set, themed per brand |
| LLC, bank account, tax return | 6if you go that far | 1 |
Counted in accounts to open, not dollars. One row does not consolidate, and it stays in the table because leaving it out would make the other ten less believable: a single Resend account carries every app, but each app still verifies its own sending domain, once.
You pay it again for every app. It is the difference between starting the next one on a Tuesday evening and scheduling it.
The money, briefly
- $59.74 a month
- four Supabase projects, between them
- $25 a month
- one project with a schema per app, on Pro
- one
- LLC, bank account, tax return
Measured 3 July 2026. A consequence of consolidating the accounts, not the reason to.
Fix it once. Every app gets it.
Six apps as six repos means six copies of auth, billing, email and analytics. The newest copy is the good one, and the other five drift a year behind. A Stripe API version bump, a CVE, a keyboard-focus bug on reset-password: on millroom each of those is one edit, because each of those things exists once. One app cannot import from another (lint blocks it), so the shared thing stays the only thing.
One that happened: core.ensure_product_org, a SECURITY DEFINER function, shipped callable by anonymous requests for about a month. One migration closed it for every app at once, and the kit's baseline ships with the fix already in.
One edit reaches
- studio
- millroom.dev, this site, docs and checkout
- cutlist
- cutlist.millroom.dev, a woodworking cut-list app
- planer
- planer.millroom.dev, an AI tool that planes rough copy down
- the next one
- whatever you build after you buy
Nine capabilities, written once.
A new app inherits all nine.
- Shared auth
src/lib/auth- Sign in once per product, MFA included. New products get auth by writing zero auth code.
- Shared billing
src/lib/billing- One Stripe webhook serves every product. Subscriptions, one-time purchases, credits, and a test-mode harness that never touches real money.
- Multi-tenant core
src/proxy.ts- A request arrives on a host. The proxy resolves the tenant, the brand, and the security headers before your code runs.
- White-label theming
core.brands- A brand is a database row. Three products in this repo wear three skins off the same components.
- AI layer
src/lib/ai- One gateway client, model tiers instead of model names, and a usage ledger that logs every call, including the failed ones.
src/lib/distribution- Themed transactional email per brand. You will not write HTML email by hand.
- Content
docs/- Blog, changelog, and these docs are markdown files. This page you are reading ships in the repo.
- Observability
src/lib/observability- PostHog events, error boundaries, and an audit trail, wired once for every product.
- Agent-first
AGENTS.md- AGENTS.md, recipes, and skills that let Claude Code or Cursor set the repo up and add products for you.
The next app adds no accounts.
Adding an app is a manifest entry, a register call, a schema of its own and one row in core.domains. The host on the request is looked up in that table by src/proxy.ts and stamped with org, app and brand before your code runs. The last app added to the portfolio this kit came out of needed exactly that, and came up with auth, themed email, billing, analytics, the component kit and the deploy already working.
A brand is one row in core.brands. Change it and the shared components restyle themselves, transactional email and OG images included. Each app still gets its own domain. None of them gets its own account.
You add
- a manifest entry
src/lib/products.ts - a register call
src/app/_products/register.ts - a schema of its own
<app>.* - a row for the host
core.domains
You do not add
- a Vercel project
- a Supabase project
- a Stripe account, webhook endpoint or signing secret
- a Resend account
- a PostHog project
- a Google consent screen
What does not consolidate.
One database, one deploy and one Stripe account are one blast radius. Compliance, outside money, or a sale you can see coming is when an app deserves its own everything, and the docs say so before you buy.
Millroom is source code. There is no admin dashboard UI, no magic links, no passkeys and no enterprise SSO; MFA enrolment is library-only. The AI layer is text only. There is no i18n, no mobile app, no multi-region and no queue.
- what it is
- a Next.js and Supabase repository, yours to run
- what it is not
- a hosted service, or a no-code builder
- what you bring
- Supabase, Stripe, Resend and PostHog accounts, one of each
Build the next one.
- one-time purchase
- no subscription, no fee per app
- full source
- build unlimited apps, do not redistribute the code
- what lands
- the source at checkout, then repository access for updates