Skip to content

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.md
  • api/v1/ is the HTTP surface — one file per resource. The route handlers are thin; the work lives in core/ and services/.
  • 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 in auth.py and deps.py.
  • models/ vs schemas/ — 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.