An opinionated spec-kit preset for FastAPI projects built on Clean Architecture (Entity-First) with async SQLAlchemy + Alembic. Encodes 12 NON-NEGOTIABLE principles into your constitution, specs, plans, tasks, and checklists.
| Group | Principle | One-liner |
|---|---|---|
| Foundation | §I. Entity-First Layering | Pydantic Entity is the domain anchor. ORM is adapter detail. Four layers, dependencies inward. |
| §II. Domain-First Project Structure | src/<domain>/ packages, not flat top-level dirs. |
|
| §III. Async-First, Always | async def everywhere; sync I/O → threadpool; CPU → external queue. |
|
| Data & Schema | §IV. Pydantic Two Layers | Pydantic serves Entity (domain) + Response (API contract, derived). |
| §V. Loader Is the Adapter Boundary | DB/RPC/cache wrapped in async Loaders; routes never import SQLAlchemy. | |
| §VI. Alembic Owns the Schema | Migrations static, reversible, descriptive slug, YYYY-MM-DD_slug.py. |
|
| Discipline | §VII. Depends for Validation | DB-backed existence/ownership checks via chained Depends(). |
| §VIII. Test-First per Endpoint | httpx + ASGITransport; ≥ 3 cases per endpoint; Loader seam for fakes. | |
| §IX. Config Decoupled per Domain | pydantic-settings per module; zero hardcoded secrets. |
|
| Ops | §X. OpenAPI Is the Contract | response_model, tags, responses=; URL versioning; prod hides docs. |
| §XI. Background Jobs Discipline | BackgroundTasks only for droppable < 1s work; else real queue. |
|
| §XII. Observability & Security | Structured logs, request IDs, /health+/ready, hashed passwords, explicit CORS. |
See templates/constitution-template.md for the full Rule / Why / How to apply / Violation signals for each principle.
The constitution's Tech Stack (locked) section pins:
- Python ≥ 3.11
- FastAPI ≥ 0.110
- Pydantic ≥ 2.5 +
pydantic-settings - SQLAlchemy ≥ 2.0 async (
asyncpg) - Alembic ≥ 1.13
httpx≥ 0.27ruff+pytest+pytest-asyncio+structlog
pydantic-resolvefor the Entity / Loader / Resolver pattern. Code examples in this preset use its API for concreteness (base_entity(),Relationship,DefineSubset,Resolver,LoaderContext). Any equivalent Resolver/Loader library or hand-rolled implementation that satisfies the layering rules (§I, §V) is acceptable.
This preset uses strategy: replace — full template overrides:
| spec-kit core template | Replaced with |
|---|---|
constitution-template.md |
FastAPI 12-principle constitution |
spec-template.md |
API-focused spec (endpoints, entities, loaders, migrations, test matrix) |
plan-template.md |
Architecture plan (layering decisions, migration sequence, test strategy) |
tasks-template.md |
Per-endpoint test-first task ordering |
checklist-template.md |
Pre-merge + pre-deploy checklist, organized by §I–§XII |
Plus two command overrides:
speckit.constitution— generates the constitution with the 12 principles baked in.speckit.specify— generates a spec that surfaces API/Entity/Loader/Migration up front.
# Inside a spec-kit-initialized project
specify preset add --dev /path/to/python-presetspecify preset list
specify preset resolve constitution-templateThe resolved path should point to .specify/presets/python-fastapi-entity-first/templates/constitution-template.md.
Once installed, the normal spec-kit workflow runs through this preset's templates:
# 1. Generate the constitution (writes .specify/memory/constitution.md)
/speckit.constitution My FastAPI project
# 2. Generate a feature spec (writes specs/<feature>/spec.md)
/speckit.specify Add a Posts domain with CRUD endpoints
# 3. Plan, tasks, implement (unchanged from core spec-kit)
/speckit.plan
/speckit.tasks
/speckit.implementThe principles are NON-NEGOTIABLE in the constitution body. To deviate:
- Don't soften the principle's language — instead, add an entry to
## Project Extensionsin the constitution:- Principle number (e.g., §V)
- Specific deviation (e.g., "raw SQL allowed in
reports/router.pyforpg_trgmsearch") - Rationale (e.g., "SQLAlchemy 2.0 lacks idiomatic support; ORM equivalent is 3× slower")
- Review/expiry date
- The principle itself stays intact and applies everywhere else.
- The Complexity Tracking table in
plan.mdmust reference this deviation.
This makes deviations explicit, traceable, and reviewable — never silent.
Per the constitution's Article Q3 (Entity-First applicability):
- Simple CRUD on a single data source — plain ORM-First is fine; this preset is overhead.
- Tiny prototype / throwaway — the layering discipline isn't worth the cost.
- Non-FastAPI Python projects — the principles are FastAPI-specific (Pydantic,
Depends, async routes).
MIT — same as spec-kit.