Skip to content

ADR 0002: Locked Stack — FastAPI + React + Postgres

Status: Accepted Date: 2026-04-29

Context

A new app is created from the template-app/ either by a human or by an AI agent. Allowing stack choices at creation time creates two problems:

  1. Agent reliability collapses when there are multiple paths. Each combination (Vue+FastAPI, React+Django, etc.) is a different surface for the agent to get wrong.
  2. Shared packages multiply. A packages/auth-client for every language/framework combination quickly becomes unmaintainable for a small team.

Decision

Every new app uses exactly one stack:

  • Frontend: React 18 + TypeScript + Vite + Tailwind.
  • Backend: Python 3.12 + FastAPI + SQLAlchemy 2.x + Alembic.
  • Database: Postgres 16, one database per app.

The template app and the scaffold script enforce this. Agents are explicitly told not to swap parts of the stack.

Consequences

Positive: - One template to maintain, one set of SDKs, one set of conventions. - Agents have a single path to follow — much higher success rate. - Onboarding (human or AI) is identical for every app. - Shared code (packages/auth-client-py, packages/ui) actually gets reused.

Negative: - Apps with genuine reasons to use a different stack (a Go service that needs raw performance, a data-science app that wants Streamlit) can't use the template. - This is acceptable — those edge cases can live as one-off services in services/ with bespoke setup, and we'd build a second template later if a pattern emerges.

Notes for future evolution

If a second stack is ever needed, the right move is a second template (template-app-go, template-app-streamlit) — not making the existing template configurable. The agent then reads the right AGENT_INSTRUCTIONS.md for whichever template the user picks.