The stack
Batteries included. All of them off.
Every subsystem here is fully wired and switched off until you say otherwise. Nothing half-works, nothing is a stub, and a clone you have just downloaded runs end-to-end without a single third-party account.
01 — The bare clone
What you get before signing up for anything
This is the whole point of flag-gating. The starter has to be fully usable on a laptop with no accounts, or the batteries are decoration.
Auth, roles and RLS multi-tenancy
Notes CRUD as the reference feature
Feedback widget
Onboarding tour
i18n, accessibility checks and the test suite
Supabase runs in Docker via pnpm supabase start, so even the database is local. The first account you create is the one you choose to create.
02 — The inventory
Every subsystem, and what it costs
Grouped the way the manifest groups them. If a row says no account, it means the feature is genuinely self-hosted — not a trial tier.
Core
Always on. No flag, because without it there is no app.
Supabase
no accountPostgres, Auth, Row Level Security, Storage and Realtime. Runs locally in Docker, so development and CI need no hosted project.
core — always on
Security
No flag — present the keys and the buttons start working.
GitHub OAuth login
needs GitHubSocial login alongside email and password. The login page buttons are already wired; you supply the client id and secret.
no flag — set 2 keys
Google OAuth login
needs GoogleThe same, for Google. Both are enabled in supabase/config.toml rather than in app code.
no flag — set 2 keys
Growth
The subsystems that grow the product. Two of them are self-hosted and cost nothing.
Email notifications
needs ResendA database trigger fans a new note out to tenant admins as notification rows; a Supabase webhook mirrors each row to email. In-app feed and bell included.
NUXT_PUBLIC_NOTIFICATIONS_ENABLED
Feedback widget
no accountA floating widget for signed-in users that submits to your own feedback table, RLS-scoped like everything else. Users read their own; admins read the tenant’s.
NUXT_PUBLIC_FEEDBACK_ENABLED
Onboarding tour
no accountA first-run product tour that targets nav links by href, so restyling the nav doesn’t break it. Completion is remembered per browser.
NUXT_PUBLIC_TOUR_ENABLED
PostHog product analytics + feature flags
needs PostHogPageviews and useFeatureFlag(key, fallback) — a reactive flag that degrades to its fallback when PostHog is off, so gated UI still works on a bare clone.
NUXT_PUBLIC_POSTHOG_ENABLED
Billing
Behind an adapter, so the provider is replaceable.
Billing
needs PolarCheckout, customer portal and webhooks behind an adapter. A Merchant of Record, which is why it is here instead of Stripe — it onboards sellers in countries Stripe will not.
NUXT_PUBLIC_BILLING_ENABLED
Observability
Also keyed rather than flagged: no DSN, no reporting.
Sentry error tracking
needs SentryError tracking, with hidden source maps generated for upload but never referenced in the bundle.
no flag — set 1 keys
BetterStack log forwarding
needs BetterStackServer log forwarding from Nitro.
no flag — set 2 keys
03 — One manifest, two scripts
Something writes it, something else checks it
pnpm setup picks the subsystems and writes .env. pnpm doctor verifies what's there. Both read the same manifest, so adding a subsystem to it wires up both — and neither can drift from the other.
$ pnpm setup
Which subsystems do you want?
◉ Feedback widget (no account needed)
◉ Onboarding tour (no account needed)
◯ Notifications (Resend)
◯ Billing (Polar)
wrote .env
$ pnpm doctor
✓ supabase 4 vars set
✓ feedback enabled, no keys required
! notifications disabled Unpicked subsystems are set to false, never deleted, and existing values are never overwritten — so re-running setup after you have edited .env by hand is safe.
doctor fails on a missing required key and warns on a missing optional one, which is how a half-configured subsystem gets caught before it is deployed rather than after.
04 — Where it runs
Vercel is the default, not the requirement
The build output is Nitro, which targets Node, Deno, Bun, Cloudflare, Netlify and a plain server. Nothing in the app reaches for a platform-specific API.
Portable by construction
Swap the Nitro preset and deploy elsewhere. The only Vercel-specific pieces are the analytics and speed-insights modules, and both no-op off Vercel.
Supabase, hosted or not
The same migrations run against a local Docker stack and a hosted project. Self-host the whole thing if you'd rather.
Migrations, not snapshots
Schema changes are ordered SQL files. After changing one, regenerate types or typecheck fails — the schema can't silently drift from the code.
Ready to wire one of these up?
The configuration reference has the exact variables and the webhook steps for each subsystem.