What's included
Everything the kit already does, so you don’t build it twice. Each line links to the page that explains it, or names the file when the code is the explanation.
Signing in and accounts
Section titled “Signing in and accounts”| What | Read more |
|---|---|
| Email and password, with a verified address required | Auth |
| Sign-in links by email, valid for 5 minutes | Auth |
| Google and GitHub, each on once you add its two values | Sign-in providers |
| The same address through Google or GitHub joins the existing account | Sign-in providers |
| Forgot and reset password; a reset ends every other session | Auth |
| A new verification link whenever someone unverified tries to sign in, and a “Send it again” button | apps/web/src/routes/check-email.tsx |
| People are returned to the page they wanted after signing in | Security |
| Profile: change name, email (confirmed in both inboxes) and password | Auth |
| “Sign out of my other devices” when changing a password | apps/web/src/features/account/password-form.tsx |
| Devices: every session with its browser and system, and sign out of the others | apps/web/src/features/account/sessions-list.tsx |
| Connect or disconnect Google and GitHub, never the last way in | apps/web/src/features/account/sign-in-methods.tsx |
| People who never set a password can ask for a link to set one | apps/web/src/features/account/password-form.tsx |
| Delete account, with the password or the typed address | Auth |
| A welcome email, once per person | Auth |
| Limits on sign-in attempts in production | Auth |
Workspaces and teams
Section titled “Workspaces and teams”| What | Read more |
|---|---|
| Personal accounts or teams, chosen with one setting, with no data to migrate later | Workspaces |
| Isolation between workspaces: guards for who gets in, queries for what comes back | Workspaces |
| Owner, admin and member roles | Workspaces |
| Invitations by email, valid for 7 days, with accept and decline screens | Workspaces |
| Seat limits per plan; a pending invitation holds a seat | Workspaces |
| A workspace switcher that reopens the last workspace you used | apps/web/src/features/workspaces |
| Members page: invite, change roles, remove, leave, cancel invitations | apps/web/src/routes/_authenticated/w.$slug/settings/members.tsx |
| Workspace settings: rename, change the address, delete by typing its name | apps/web/src/routes/_authenticated/w.$slug/settings/workspace.tsx |
| API keys for programs: a role each, an expiry, a rate limit, shown once | Auth |
| Deleting a workspace cancels its subscription first | Billing |
Billing
Section titled “Billing”| What | Read more |
|---|---|
| Plans written once in code; the API, billing page, pricing page and provider follow | Charge for a feature |
| Stripe, or Polar as merchant of record handling sales tax and VAT, chosen with one setting | Polar |
billing:sync creates and updates products and prices in Stripe or Polar, and says whether it is in test or live mode |
Stripe |
No price ids in your environment: prices are found by a key such as pro_month |
Stripe |
| Monthly and yearly prices, flat or per seat | Charge for a feature |
| Usage-based billing: an allowance a month on each plan, then a price per unit, metered at Stripe or Polar | Charge for usage |
| Checkout, with promotion codes accepted | Billing |
| The provider’s customer portal for cards, invoices, plan changes and cancelling | Stripe |
| Webhooks that are verified, safe to receive twice and safe out of order | Billing |
| A failed payment keeps the plan while the provider retries, then drops to free | Billing |
| Per-seat bills follow the team as people join and leave, prorated | Billing |
| A receipt email for every payment, with a link to the invoice | Billing |
@RequireFeature() in the API and <RequireFeature> on screen, with an upgrade prompt |
Charge for a feature |
| The billing page waits for the payment to confirm, then says so | apps/web/src/routes/_authenticated/w.$slug/settings/billing.tsx |
| Everything works without a payment provider’s key: every workspace is on the free plan | Billing |
billing:listen forwards webhooks to your machine without stripe login |
Stripe |
| What | Read more |
|---|---|
| Eight emails: verify, welcome, sign-in link, reset password, change email, invitation, receipt, contact message | apps/api/src/mail/templates |
| Each sent as HTML and as plain text, from one layout with your colour | Send email |
| A live preview of every template | Send email |
| Sent through the queue: retried for about 2 hours when your provider is down | Email provider |
| Sent only if the change is saved, and only once | Send email |
| Any SMTP provider; a local inbox that catches everything while you develop | Email provider |
Background jobs
Section titled “Background jobs”| What | Read more |
|---|---|
| BullMQ on Redis, fed from an outbox in Postgres | Background jobs |
| Payloads checked against a schema when queued and again when run | Background jobs |
| Queue inside a transaction, once per key, or for later | Background jobs |
| Retries that wait longer each time, from 15 seconds up to an hour | Background jobs |
| A job whose worker died is picked up again by BullMQ within a minute | Background jobs |
| Schedules written as cron, run once however many workers there are | Background jobs |
| Finished jobs cleaned up nightly: done after 7 days, failed after 30 | apps/api/src/jobs/jobs.cleanup.ts |
| Workers in the API or in their own service, any number of them | Background jobs |
| Jobs in progress finish before a worker stops | Health checks |
Activity log
Section titled “Activity log”| What | Read more |
|---|---|
| Workspace, member, invitation and billing changes recorded from the start | Record activity |
| Recorded in the same transaction as the change | Record activity |
| A page that reads as sentences, for admins and owners, as a paid feature | Record activity |
| What support did while signed in as a customer is marked “by support” | Admin panel |
| The name and address of whoever did it are kept after their account is gone | apps/api/src/db/schema |
Admin panel
Section titled “Admin panel”| What | Read more |
|---|---|
| Sign-ups this week, subscriptions per plan, failed payments | Admin panel |
| Everyone who signed up, with search, last visit and plan | Admin panel |
| Every workspace with its owner, plan and subscription | Admin panel |
| Sign in as a customer for up to an hour, with a banner and a Stop button | Admin panel |
| Suspend someone and lift it again | Admin panel |
@AdminOnly() for routes of your own |
Admin panel |
| What | Read more |
|---|---|
| An assistant chat that streams, with a Stop button | AI features |
| Any model through Vercel AI Gateway, changed with one variable | AI features |
| A paid feature, scoped to the workspace | AI features |
| Limits on what is sent and how long the answer is | AI features |
| Off until you add a key, so development and CI need none | AI features |
| Streamed answers are not held back by the proxy in production | apps/web/Caddyfile |
Product analytics
Section titled “Product analytics”| What | Read more |
|---|---|
| Events named once in the contracts, sent from the API, web and mobile apps | Product analytics |
| Sign-ups, invitations and every change of plan, sent by the API through jobs | Product analytics |
| People identified on sign-in, and grouped by workspace with teams on | Product analytics |
| Mixpanel or PostHog (US, EU or your own), chosen with one variable | Mixpanel or PostHog |
| An interface in each app for another provider | Product analytics |
| Off until you add a key: no script downloaded, nothing sent | Product analytics |
Web app
Section titled “Web app”| What | Read more |
|---|---|
| A shell with a sidebar that collapses, and slides over the page on phones | apps/web/src/features/shell |
| Light, dark or the device’s choice, with no flash on load | apps/web/src/lib/theme.ts |
| A get-started checklist for new customers, ticked off from what they did | apps/web/src/features/onboarding |
| A notification bell with an unread count, live, and a page of where they go | Notifications |
| Upgrade prompts with the plan’s price and perks; the recommended plan marked | Charge for a feature |
| Every answer from the API checked against its contract | Architecture |
| Forms validated with the same schemas as the API | Add a resource |
useWorkspace() with can() for roles and has() for plans |
Architecture |
| Confirmation dialogs that can ask for a password or a typed name | apps/web/src/components/confirm-dialog.tsx |
| Search boxes and pagers that keep their state in the address | apps/web/src/components/list-controls.tsx |
| Pages split into their own files, loaded when a link is about to be clicked | apps/web/src/main.tsx |
| One “Page not found” for pages that do not exist and pages you may not see | apps/web/src/routes/__root.tsx |
| An overview page with team, plan and system status cards to replace | apps/web/src/routes/_authenticated/w.$slug/index.tsx |
| A banner on every page of a public demo, with the test card | Marketing site |
Marketing site
Section titled “Marketing site”| What | Read more |
|---|---|
| Home, pricing, about, contact, blog, terms, privacy and a 404 page | Marketing site |
| Pricing drawn from your plans, with a monthly and yearly switch | Marketing site |
| A blog in MDX with tags, drafts, reading time and an RSS feed | Marketing site |
| A share image made for every page and post | Marketing site |
Canonical links, Open Graph and Twitter cards, JSON-LD, a sitemap, robots.txt |
apps/site/src/layouts/Base.astro |
| A contact form that emails you, with a trap for bots and a limit per address | Marketing site |
| Terms and privacy templates | Marketing site |
| Follows the device’s dark mode | apps/site/src/layouts/Base.astro |
Mobile app
Section titled “Mobile app”| What | Read more |
|---|---|
| An Expo app on the same contracts, with the same checked API client | apps/mobile/src/lib/api.ts |
| Sign-in with a password, Google or GitHub, the session kept in the device’s secure storage | Mobile app |
| Sign-up, forgot password, and deleting the account from inside the app | Mobile app |
| Workspace switching, people and invitations, with teams on | Mobile app |
| The audit log, for admins on a plan that has it | Mobile app |
| The assistant, streamed, and the plan and what it includes | Mobile app |
| Push notifications through the job queue, one call from any module | Mobile app |
| A Notifications tab with an unread badge, live, and a screen to choose what reaches the phone | Notifications |
| Bottom tabs drawn by the system (glass on iOS 26), and light, dark or system theme | Mobile app |
| EAS profiles for development, testers and the stores | Mobile builds |
The API underneath
Section titled “The API underneath”| What | Read more |
|---|---|
| Contracts shared by the API, web and mobile: change a field and they stop compiling | Architecture |
| Guards for sessions, admins, membership, roles and plans, in that order | Architecture |
Every error in one shape, apiErrorSchema |
packages/contracts/src/errors.ts |
| Environment variables checked at startup, with one clear line per mistake | Environment variables |
| Structured logs with a request id on every line and every response | Logs |
| Secrets kept out of the logs, with a test that keeps it so | Logs |
| OpenTelemetry traces across requests, jobs and queries, and metrics, with one variable | Traces and metrics |
| Errors from the API, web and mobile apps reported to Sentry, with one variable | Error reporting |
| Source maps sent by the web and mobile builds, never served | Error reporting |
| Reports without passwords, tokens, cookies or emails, with a test | Error reporting |
| A health check that knows about the database | Health checks |
| Stops cleanly: finishes its work and closes its connections | Health checks |
| Redis: the job queue, realtime, answers in flight, shared rate limits and a cache | Redis |
| Drizzle, Prisma or TypeORM, chosen once; the kit works with any, tested on all three | Database and ORMs |
| Migrations with your ORM, run before each release | Other hosts |
db:migrate needs only DATABASE_URL, so it runs before the rest is set up |
apps/api/src/db/migrate.ts |
Tests and code quality
Section titled “Tests and code quality”| What | Read more |
|---|---|
| 300 API tests against a real Postgres and Redis, on each ORM | Test your features |
| Browser journeys against the production images, in both modes, on every pull request | Test your features |
| The mobile app’s flows with Maestro, on iOS and Android, and Android in CI on demand | Test your features |
| Helpers to sign people up, add members and read their email | Test your features |
| Stand-ins for Stripe, Polar, email and the AI model; no test reaches a real service | Test your features |
| Either mode and any pricing, per test | Test your features |
bun run check: types, lint, formatting and every test, in one command |
Commands |
| Strict TypeScript everywhere, oxlint and Prettier | tsconfig.base.json, .oxlintrc.json, .prettierrc |
| GitHub Actions on every pull request, with no secrets to set | Continuous integration |
| The production images built, started and checked on every pull request | Continuous integration |
Deploying and running it
Section titled “Deploying and running it”| What | Read more |
|---|---|
| Postgres, Redis, API, web, site and an optional worker on Railway, from one file | Railway |
deploy:plan shows what would change before deploy:apply changes it |
Railway |
| A guard that refuses to touch the wrong Railway project | Railway |
| Migrations before each release; if they fail, the old version keeps serving | Railway |
| Only the services whose files changed are rebuilt | Railway |
| Health checks on every service, and restarts when one exits | Health checks |
| The same production on AWS from one command: ECS, RDS and ElastiCache, in the CDK | AWS |
| Settings kept in Secrets Manager on AWS, never in a template | AWS |
| Settings checked against the API’s own rules before every deploy | Check a deployment |
deploy:check: sixteen checks of a deployment from outside, on any host |
Check a deployment |
| Production described once, apart from any host, and a guide and skill to add a host | Add a host |
| Docker images for any host, and the production setup on your own machine | Try it locally |
| One address in production: no CORS to set up, first-party cookies | Architecture |
| Security headers, compression and long-lived caching of files that never change | Security |
| Your own domains | Railway |
| A launch checklist | Launch checklist |
For your coding agent
Section titled “For your coding agent”| What | Read more |
|---|---|
AGENTS.md at the root and in each app, read by Claude Code, Cursor and Codex |
Build with your coding agent |
| Ten skills, each ending in a checklist of what must be true | Build with your coding agent |
| Upgrade notes for every release, and a skill that applies them on a branch | Make it yours |
These pages in the repository, in docs/ |
Overview |