Architecture Overview
Leave Localhost is a full-stack SaaS starter built on Next.js (frontend) and Convex (backend), structured as a Turborepo monorepo. It ships authentication, multi-tenancy, billing, transactional email, analytics, and error tracking so you can focus on product code.
Leave Localhost is a full-stack SaaS starter built on Next.js (frontend) and Convex (backend), structured as a Turborepo monorepo. It ships authentication, multi-tenancy, billing, transactional email, analytics, and error tracking so you can focus on product code.
Tech Stack
| Layer | Technology |
|---|---|
| Frontend framework | Next.js 15 (App Router) |
| Backend | Convex (real-time, serverless) |
| Authentication | Better Auth (via @convex-dev/better-auth) |
| Billing | Polar, Stripe, or Lemon Squeezy (pluggable) |
| UI components | shadcn/ui, Radix, Tailwind CSS 4 |
| Resend + React Email | |
| Analytics | PostHog (optional) |
| Error tracking | Sentry |
| Logging | Convex-native logs (backend) + platform console (apps) |
| Monorepo | Turborepo + Bun |
| Validation | Zod, @t3-oss/env-core |
High-Level Flow
┌──────────────────────────────┐
│ User's Browser │
├──────────────────────────────┤
│ apps/app (Next.js) │ ◄── Authenticated product app
│ apps/marketing (Next.js) │ ◄── Marketing site
├──────────────────────────────┤
│ packages/ui │ ◄── Shared components & tokens
│ packages/analytics │ ◄── PostHog + no-op (provider-neutral)
│ packages/email │ ◄── React Email preview workspace
└──────────┬───────────────────┘
│ Convex client SDK (real-time subscriptions, mutations, actions)
▼
┌──────────────────────────────┐
│ packages/backend/convex │
│ ─────────────────────────── │
│ Schema, queries, mutations, │
│ actions, auth, billing, │
│ permissions, email, │
│ webhooks, cron jobs │
└──────────┬───────────────────┘
│
┌──────┴──────┐
│ Convex DB │ ◄── Transactional, real-time document database
└─────────────┘Key Design Decisions
Backend as a Package
The Convex backend is a standalone package at packages/backend rather than
co-located with the frontend. This lets both apps/app and apps/marketing import
backend types and client bindings without duplicating schema definitions.
Capability-Based Permissions
Permissions combine role-based access (via Better Auth organizations) with capability-based entitlements (granted by billing plans). A function can require both a specific role and a specific capability, ensuring that paid features remain locked even if a user has the correct role.
Provider-Agnostic Billing
Billing is abstracted behind a BillingProviderAdapter interface and ships
opt-in. All provider integrations are compiled in and registered in
billing/providers.ts; a provider is activated solely by setting
BILLING_PROVIDER. With it unset, no webhook route is registered and billing is
disabled. Webhooks from the active provider converge into a shared grant
system — the rest of the codebase checks capabilities, not provider-specific
subscription states.
Real-Time by Default
Convex queries are reactive subscriptions. When data changes in the database, all connected clients that subscribe to affected queries receive updated results automatically. The dashboard uses this for the optional workspace records demo, member lists, and billing state.
Next Reads
- Monorepo — Turborepo workspace structure and commands.
- Convex Backend — the Convex backend architecture.
- Data Model — the database schema.
- Security Model — authentication, authorization, and step-up verification.
- Server Actions and Functions — Convex function patterns.
- AI Agent Guidelines — rules for AI agents editing the codebase.
Delete Before Launch
This starter includes demo surfaces, placeholder configuration, and example business rules. Remove or replace them before a real production launch.
Monorepo
Leave Localhost is organized as a Turborepo monorepo managed with Bun. This structure lets all apps and packages share types, utilities, and build configuration while remaining independently deployable.