Project Structure
A new codebase you cannot navigate is a liability, not a head start. The Unsexy Stack is a conventional two-service layout with one obvious home for every concern. This is the actual shipped structure.
the-unsexy-stack/ backend/ app/ api/v1/ # routers: health, users, billing, webhooks router.py # wires the v1 routes together users.py # GET /users/me (auto-provision on first visit) billing.py # POST /billing/checkout, /billing/portal webhooks.py # POST /webhooks/stripe (idempotent) health.py # GET /health core/ config.py # typed Settings (Pydantic BaseSettings) from env auth.py # JWKS-cached Clerk RS256 verification + thundering-herd lock deps.py # FastAPI dependencies: DB session, current user (race-safe) database.py # async SQLAlchemy engine + session factory middleware.py # request-ID + Clerk-user context rate_limit.py # slowapi limiter errors.py # structured error handling logging_config.py models/ # SQLAlchemy 2.0 typed models (async sessions/engine) base.py # UUID + timestamp mixins user.py # the user table (tier CheckConstraint at the DB) webhook_event.py schemas/ # Pydantic v2 request/response models services/ # Stripe + business logic main.py # FastAPI app factory alembic/ # async migrations (versions/ + env.py) tests/ # 144 backend tests (pytest) pyproject.toml # deps + ruff + pytest config frontend/ src/ app/ # Next.js 15 App Router dashboard/ # protected example page sign-in/ sign-up/ # Clerk routes layout.tsx page.tsx globals.css components/ # query-provider, etc. lib/ # api client middleware.ts # Clerk auth + protected routes package.json tsconfig.json infra/ nginx/ # reverse-proxy config systemd/ # backend.service + frontend.service docker/ # Professional + Agency: compose + multi-stage Dockerfiles .github/workflows/ # Agency tier: CI/CD (ci, codeql, deploy) docs/ # guides + PDFs + SECURITY_CHECKLIST + ARCHITECTURE Makefile # make dev / test / lint / migrate / setup README.md START_HERE.md LICENSE.mdHow to read it
Section titled “How to read it”api/v1/is the HTTP surface — one file per resource. The route handlers are thin; the work lives incore/andservices/.core/is the engine room: configuration, auth, the DB session, and the cross-cutting middleware. The two hard parts — JWKS-cached auth and race-safe provisioning — live inauth.pyanddeps.py.models/vsschemas/— SQLAlchemy models are your database shape; Pydantic schemas are your API contract. They are deliberately separate, so your wire format never leaks your tables.infra/holds the deploy artifacts. systemd + nginx and Docker Compose ship in Professional and Agency; CI/CD workflows are the Agency tier add-on.
Everything has one obvious place. You will know where to add your first feature before you finish
your coffee. The full architecture write-up ships as docs/ARCHITECTURE.md in the download.