Skip to content

Latest commit

 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Scalable Starter

A production-grade, platform-agnostic full-stack skeleton. Next.js + FastAPI · built to scale on Kubernetes · zero business logic.

Fork it, delete the example feature, and ship your product on day one instead of spending the first month wiring config, logging, auth scaffolding, migrations, containers, CI, and Kubernetes manifests.

CI CodeQL License: MIT PRs welcome

Quickstart · Architecture · Add a feature · Deploy · ARCHITECTURE.md · docs/

Next.js React TypeScript FastAPI Python PostgreSQL Redis Docker Kubernetes


Why this exists

Every new product starts with the same three weeks of undifferentiated plumbing. This repo is that plumbing, done once and done well, so you never write it again.

It is deliberately empty of features. There is exactly one trivial example endpoint (/api/v1/items) wired end-to-end — frontend to API to service to repository to database — purely to show you the seams. Delete it and the skeleton still stands.

What you get instead of features:

  • A real architecture, not a single file that grows into a swamp. Clear layers (transport, service, repository, data) with dependency rules that keep a 200-file codebase as navigable as a 20-file one.
  • Horizontal scalability baked in. Stateless services, externalized session/cache, health/readiness probes, graceful shutdown, and a Kubernetes HPA so the answer to "we got traffic" is "it already scaled."
  • Platform-agnostic. Run it with docker compose up on a laptop, or kubectl apply -k on any conformant cluster (EKS, GKE, AKS, k3s, kind). No managed-service lock-in is assumed.
  • Opinionated defaults, swappable parts. Postgres + Redis today; the repository and cache interfaces mean you can swap them without touching business code.
  • The boring, critical stuff is finished: typed config, structured logging with request-ID correlation, RFC-9457 error responses, CORS, rate-limit hook, OpenTelemetry tracing, Prometheus metrics, migrations, tests, multi-stage non-root Docker images, and CI that runs the same checks you run locally.

If you are a startup or a "vibe coder," the goal is simple: git clone, make up, start building the thing that actually makes you different.


What's in the box

Layer Choice Why
Frontend Next.js 16 (App Router) + React 19 + TS SSR/RSC, huge ecosystem, the default for fast product work
Backend FastAPI + Python 3.13 Async, type-driven, auto OpenAPI, gentle learning curve
Validation/DTOs Pydantic v2 Fast, strict, the FastAPI-native contract layer
Data access SQLAlchemy 2.0 (async) + Alembic Mature ORM + first-class migrations
Database PostgreSQL The dependable default for 99% of products
Cache / broker Redis Cache, rate-limit store, lightweight queue
Monorepo pnpm workspaces + Turborepo One repo, fast cached builds, shared types
Containers Multi-stage Docker (non-root) Small, reproducible, secure images
Orchestration Kubernetes + Kustomize Cloud-agnostic, base + per-env overlays, HPA autoscaling
Observability OpenTelemetry + Prometheus + structured logs Traces, metrics, logs correlated by request ID
CI/CD GitHub Actions Lint, typecheck, test, build, image — mirrors make check

See ARCHITECTURE.md for the full design rationale and docs/adr/ for the decision records behind each choice.


AI agents follow your rules, not their defaults

Most code in a fork like this won't be typed by you — it'll be written by Claude, Cursor, Copilot, or whatever agent comes next. So this starter keeps the rules in the repo, machine-readable, and every fork inherits them: any agent that opens your code is told how to work here before it writes a line.

That's not only the system design (stateless, layered, migration-owned schema) — it's a full code of conduct: understand the code and find the right place before changing it, no hardcoding, find the best solution rather than the first, keep changes minimal and finished, verify before claiming done, and report honestly.

File Read by
AGENTS.md the cross-tool standard — Claude, Cursor, Codex, Gemini CLI, …
CLAUDE.md Claude Code (auto-loaded)
.cursor/rules/ · .github/copilot-instructions.md Cursor · GitHub Copilot
.claude/skills/add-feature/ an invokable skill for the highest-drift task (adding a resource)

These are guidance, not gates — on purpose. When you fork this repo they come with it, so every agent working in your codebase reads and follows them by default, and a reviewer (human or AI) can cite them to raise concerns at review time. They never hard-block: your product might genuinely need to break a rule, and that's your call — just write it down (an ADR in docs/adr/). The only things that must pass are the ordinary quality gates you already run — make check: lint, types, tests, formatting, and contract sync.


Architecture

flowchart TB
    subgraph client["Client"]
        B["Browser / Mobile"]
    end
    subgraph edge["Edge"]
        IG["Ingress / Load Balancer<br/>(TLS, routing)"]
    end
    subgraph cluster["Kubernetes cluster"]
        subgraph webd["web Deployment (N pods, HPA)"]
            W["Next.js<br/>SSR + RSC"]
        end
        subgraph apid["api Deployment (N pods, HPA)"]
            A["FastAPI<br/>stateless"]
        end
        WK["worker Deployment<br/>(background jobs)"]
    end
    subgraph data["Stateful backing services"]
        PG[("PostgreSQL<br/>primary + replicas")]
        RD[("Redis<br/>cache / broker")]
    end
    OTEL["OpenTelemetry Collector"]
    PROM["Prometheus / Grafana"]

    B --> IG
    IG -->|"/"| W
    IG -->|"/api"| A
    W -->|"server-side fetch"| A
    A --> PG
    A --> RD
    A -. "enqueue" .-> RD
    RD -. "dequeue" .-> WK
    WK --> PG
    A -. "traces/metrics" .-> OTEL
    WK -. "traces/metrics" .-> OTEL
    A -. "/metrics scrape" .-> PROM
Loading

The backend follows a layered (ports-and-adapters) architecture. Dependencies point inward only — transport knows about services, services know about repositories, nothing in the core knows about HTTP or SQL specifics:

flowchart LR
    HTTP["API layer<br/>routers, deps, middleware"]
    SVC["Service layer<br/>use-cases / business rules"]
    REPO["Repository layer<br/>data-access interfaces"]
    DB[("DB / Redis<br/>adapters")]
    HTTP --> SVC --> REPO --> DB
Loading

Full request lifecycle, scaling model, and failure handling live in ARCHITECTURE.md.


Repo layout

scalable-starter/
├── apps/
│   ├── web/                  # Next.js frontend (App Router, TS strict)
│   │   ├── app/              # routes, layouts, route handlers
│   │   ├── components/       # presentational components
│   │   └── lib/              # api-client, typed env, utils
│   └── api/                  # FastAPI backend (layered)
│       └── app/
│           ├── core/         # config, logging, security, lifespan
│           ├── api/v1/       # routers + dependencies (transport)
│           ├── services/     # use-cases (business rules)  <-- your logic
│           ├── repositories/ # data-access interfaces + impls
│           ├── schemas/      # Pydantic DTOs (the API contract)
│           ├── db/           # async engine, session, models
│           ├── middleware/   # request-id, timing, error handling
│           ├── observability/# tracing + metrics
│           └── workers/      # background job consumer skeleton
├── packages/                 # shared TS packages (tsconfig, eslint, api-contract)
├── infra/
│   ├── docker/               # multi-stage Dockerfiles
│   └── k8s/                  # kustomize: base/ + overlays/{dev,staging,prod}
├── docs/                     # guides, ADRs, improvement log
├── .github/workflows/        # CI/CD
├── docker-compose.yml        # local dev stack
├── Makefile                  # every command you need (`make help`)
└── ARCHITECTURE.md           # the system design, in depth

Quickstart (2 commands)

Option A — Docker (recommended, nothing to install but Docker):

cp .env.example .env
make up           # builds & starts web + api + postgres + redis

Option B — Local dev (hot reload, requires Node 20+ and Python 3.12+):

make setup        # installs JS + Python deps, creates .env
make migrate      # apply database migrations
make dev          # runs web and api in watch mode

Run make help to see every available command.


Add a feature in 5 minutes

The skeleton's whole point is that adding a feature is mechanical. To add a projects resource you touch one file per layer — the example items feature is your copy-paste template:

  1. Modelapp/db/models/project.py, exported from models/__init__.py so Alembic sees it.
  2. Schemaapp/schemas/project.py: Pydantic ProjectCreate / ProjectRead.
  3. Repositoryapp/repositories/project.py: subclass the generic async repo.
  4. Serviceapp/services/project.py: your business rules.
  5. Routerapp/api/v1/routes/projects.py: thin HTTP layer, calls the service.
  6. Register the router in app/api/v1/router.py, run make migration m="add projects", and you're done.

The frontend mirrors this: add a typed client call in lib/api-client.ts and a route under app/. See docs/guides/adding-a-feature.md.


Deploy

Anywhere Docker runs — build the images directly:

docker build -f infra/docker/api.Dockerfile -t myreg/app-api:tag .
docker build -f infra/docker/web.Dockerfile -t myreg/app-web:tag .

Kubernetes (any conformant cluster — EKS, GKE, AKS, k3s, kind):

kubectl kustomize infra/k8s/overlays/prod   # inspect what will be applied
kubectl apply -k infra/k8s/overlays/prod    # apply it

Each overlay (dev / staging / prod) patches replica counts, resource limits, image tags, and env without duplicating the base manifests. Autoscaling (HPA), pod-disruption budgets, network policies, and liveness/readiness probes are part of the base. See docs/guides/deployment.md and docs/guides/scaling.md.


Swap the defaults

Nothing here is load-bearing if you don't want it to be:

  • Different database? Implement the repository interface against your store; services never see SQL.
  • Different frontend (mobile, another SPA)? The API is a clean, documented OpenAPI surface — point any client at it.
  • Different Python framework or even language? The layered boundaries and the infra/ + docs/ scaffolding transfer; only apps/api/app changes.
  • Serverless instead of K8s? The stateless API and typed config port cleanly; drop infra/k8s and add your platform's adapter.

License

MIT — do whatever you want. Attribution appreciated, not required.

About

Production-grade, platform-agnostic full-stack skeleton: Next.js 16 + FastAPI, built to scale on Kubernetes. Zero business logic.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages