A community-driven registry for Claude, Cursor, Windsurf, Cline & more. Not affiliated with Anthropic.
Are you the author? Sign in to claim
Agent-first FastAPI template built to pair with Claude Code - opinionated architecture kept on the rails by custom skill
Production-ready FastAPI template with Clean Architecture, multi-transport support (HTTP / NATS consumers / Taskiq scheduler), and first-class Claude Code integration — custom skills, architecture hooks, and a review agent that teach the AI how the codebase is structured.
A batteries-included starting point for building async Python services. Ships with the boring-but-important stuff already wired: Dishka DI across three transports, SQLAlchemy 2.0 async + Alembic, Pydantic v2 contracts, JWT auth, pagination, layered testing with testcontainers, and strict layer boundaries enforced by Claude Code hooks so the architecture stays clean as the project grows.
application/ → database/ is the only documented exception). The full ruleset lives in CLAUDE.md.FastAPI + Granian), message consumers (FastStream over NATS), scheduled jobs (Taskiq over NATS JetStream). All share the same Dishka container built by entrypoints/container.py.Request, calls request_bus.send(), and unwraps a Result. Zero business logic in endpoints/subscribers/tasks. Paired with an EventBus for fire-and-forget domain events, both inheriting a shared Bus[M] Protocol.public/, user/, admin/, internal/). Auth is wired once at the router level; it's structurally impossible to forget on individual endpoints.10 ≤ limit ≤ 200; internal callers can request unbounded fetches via limit=None.testcontainers Postgres/Redis/NATS), e2e (full HTTP stack via httpx.AsyncClient + ASGITransport).usecase / endpoint / repository / migration / tests / api-client, pre-commit hooks that block layer violations and protected-path edits, an architecture review agent, and a CLAUDE.md that's the authoritative spec.| Area | Stack |
|---|---|
| Runtime | Python 3.12+, uv for deps |
| Web | FastAPI 0.115+, Granian (Rust-based ASGI server) |
| DI | Dishka — scoped IoC container, one source of truth across HTTP / consumers / tasks |
| DB | SQLAlchemy 2.0 (async) + asyncpg, Alembic migrations |
| Validation | Pydantic v2 (frozen Request models, strict Contract models) |
| Cache | Redis (redis.asyncio) |
| Messaging | NATS (nats-py, FastStream for subscribers, Taskiq-NATS for cron jobs) |
| Security | PyJWT (HS256/RS256), Argon2 password hashing, AES for sensitive fields |
| Serialization | orjson (HTTP), msgpack (broker payloads) |
| Tooling | Ruff + MyPy (strict), pytest + pytest-xdist + testcontainers |
uv sync
make docker-dev-up
.envCopy the example settings and fill in cipher keys / DB credentials (see src/settings/core.py for all fields):
cp .env.example .env
Required keys: DB_*, REDIS_*, NATS_*, CIPHER_* (ALGORITHM, SECRET_KEY, PUBLIC_KEY — for HS256 set SECRET_KEY == PUBLIC_KEY, ACCESS_TOKEN_EXPIRE_SECONDS, REFRESH_TOKEN_EXPIRE_SECONDS).
make upgrade
# HTTP API (FastAPI + Granian)
make run-http
# or: uv run python -m src.entrypoints.http
# Message consumer (FastStream over NATS)
make run-consumers
# or: uv run faststream run src.entrypoints.consumers:app
# Scheduler (Taskiq)
make run-worker # uv run taskiq worker src.entrypoints.tasks:broker
make run-scheduler # uv run taskiq scheduler src.entrypoints.tasks:scheduler
Each transport has its own entry point under src/entrypoints/ and all three share the same Dishka container built by entrypoints/container.py::build_container(settings, *extras).
src/
├── application/ USE CASES — transport-agnostic business logic
│ ├── common/ ports (Hasher, Cache, JWT, Bus, RequestBus, EventBus, Broker), bus implementations, exceptions, Request base, OffsetPagination
│ └── v1/ usecases, services, results, events, constants
│
├── infrastructure/ OUTBOUND ADAPTERS — Redis, Argon2, PyJWT, aiohttp, NATS brokers, logging
│
├── database/ PERSISTENCE — first-class layer (shared kernel)
│ ├── models/ SQLAlchemy ORM (inherit Base with .as_dict())
│ ├── repositories/ create/select/select_many/update/delete/exists/count/upsert — fixed vocabulary
│ ├── queries/ Query Object pattern for complex SQL
│ └── types/ OrderBy, Loads literals, TypedDict payloads
│
├── presentation/ INBOUND ADAPTER — FastAPI HTTP
│ └── http/v1/
│ ├── contracts/ Pydantic request/response schemas + strict OffsetPagination
│ ├── guards/ Authorization (JWT + role check)
│ └── endpoints/ audience-first: public/, user/, admin/, internal/
│
├── consumers/ INBOUND ADAPTER — FastStream (NATS subscribers)
├── tasks/ INBOUND ADAPTER — Taskiq (scheduled jobs)
│
├── entrypoints/ composition root: http.py, consumers.py, tasks.py, container.py
├── common/ leaf utilities (Dishka helpers, formatters, types)
└── settings/ Pydantic Settings
See CLAUDE.md for the full architecture spec — layer rules, DBGateway patterns, list endpoint shape, ORM→Result mapping, naming conventions.
Three layers, marked and parallelized via pytest-xdist:
uv run pytest tests/unit/ # no I/O, mocks/fakes only (~1s)
uv run pytest tests/integration/ # real Postgres/Redis/NATS via testcontainers
uv run pytest tests/e2e/ # full HTTP stack via httpx.AsyncClient + ASGITransport
uv run pytest # all of the above
Test infrastructure notes:
tests/conftest.py spins up containers once per session, runs Alembic migrations in a sync context (migration env uses asyncio.run internally), creates a per-worker DB for xdist isolation.httpx.AsyncClient + httpx.ASGITransport (not TestClient) to keep asyncpg connections on the same event loop as the app, avoiding the classic "attached to a different loop" trap.This template is designed to be developed with an AI assistant, not in spite of one. The .claude/ directory ships opinionated configuration so Claude Code understands the codebase rules, enforces them automatically, and can scaffold new features consistently.
.claude/skills/)Custom skills that kick in when Claude is working on a specific kind of file. Each skill is a self-contained SKILL.md with examples, anti-patterns, and checklists.
| Skill | Triggers when… | Enforces |
|---|---|---|
usecase | editing src/application/v1/usecases/ | RequestBus + UseCase pattern, @dataclass(slots=True), Request in the same file, DBGateway transaction rules (pattern 1/2/3), {Entity}Result(**orm.as_dict()) over model_validate(orm), the list-endpoint shape for select_many use cases |
endpoint | editing src/presentation/http/v1/endpoints/<audience>/ | audience-first organization, the five-parameter list shape (request_bus / query / pagination / loads / return), parameter naming (query for GET filters, data for POST/PATCH/PUT bodies), strict contract ↔ Result mapping, privileged-field lockdown between UpdateSelf vs AdminUpdateX contracts |
repository | editing src/database/psql/repositories/ | the fixed CRUD verb vocabulary (create, select, select_many, update, delete, exists, count, upsert — no invented names like find_one or save), @on_integrity for unique constraints, sqla_select for single-row eager loading, sqla_offset_query / sqla_cursor_query for paginated reads, unique_scalars(...).first()/.all() for materialisation, Result[T] return wrapping, limit: Optional[int] = None for unbounded internal callers |
migration | adding/changing schema | migrations are generated via make generate NAME=..., never hand-written; existing files in migrations/versions/ are immutable history; data migrations + enum additions need manual op.execute |
tests | editing tests/unit/, tests/integration/, tests/e2e/ | per-use-case unit coverage, per-endpoint e2e coverage, mutation-persistence tests (follow every PATCH/POST with a GET to verify the change landed — not just assert 200), Contract↔Request field-mismatch detection, loads= opt-in-and-opt-out flow tests, authorization matrix (unauth + wrong-role), contract validation boundaries, and the e2e infra gotchas (httpx.AsyncClient + ASGITransport instead of TestClient, sync alembic fixture, session-scoped asyncio loop, HS256 key matching) |
api-client | integrating a new external HTTP API | the Client + Service split — Client lives under infrastructure/http/clients/ and returns raw vendor-shaped Pydantic responses, Service lives under application/ and maps vendor shapes into domain Results; one provider-agnostic AsyncProvider is shared by all clients via the middleware chain |
.claude/hooks/)Runtime guards that execute on every tool call. Claude is blocked before it can make an architectural or safety mistake.
| Hook | Event | What it does |
|---|---|---|
guard_layers.py | PreToolUse on Edit/Write/MultiEdit | Parses the new file content and blocks imports that would violate the layer dependency rules (e.g. application/ importing infrastructure/, presentation/ importing consumers/). The documented application → database exception is allowed. |
guard_paths.py | PreToolUse on Edit/Write/MultiEdit | Blocks edits to protected files: committed Alembic migrations (migrations/versions/NN_*.py), migrations/env.py, lockfiles (uv.lock), .env* secrets, pyproject.toml. Forces Claude to go through proper tooling (make generate, uv add). |
pre_commit_checks.py | PreToolUse on Bash when command matches git commit | Runs ruff check + mypy --strict on src/ and tests/ before allowing the commit. Failed checks block the commit with the errors printed back to Claude to fix. |
ruff_fix.py | PostToolUse on Edit/Write/MultiEdit | Silently runs ruff format + ruff check --fix on the edited Python file. Keeps formatting consistent without cluttering Claude's context. |
Hooks live in .claude/settings.json — the repo-committed config. No machine-specific state.
.claude/agents/)| Agent | Purpose |
|---|---|
architecture-reviewer | On-demand architecture & authorization reviewer. Reads CLAUDE.md, walks git diff or specified files, flags layer violations, DBGateway misuse, privileged fields leaking into user contracts, missing role checks, and response-body leaks. Produces a structured Critical/Architecture/Advisory report. Never modifies files. |
CLAUDE.mdThe authoritative project spec that Claude Code reads as part of its context on every session. It documents:
database/ exception and when it appliesDBGateway usage rules with the three canonical patterns (read / write / read-then-write) and the anti-pattern tableBase.as_dict() vs model_validate(orm) — the lazy-load footgun explainedloadsOffsetPagination split (presentation vs application)OffsetResult.map() for Result → Contract conversionEventBus and the Bus[M] parent Protocol)query vs POST data, OpenAPI tags)If a rule isn't in CLAUDE.md, it isn't a rule.
make install # uv sync --all-groups
make upgrade # alembic upgrade head
make downgrade # alembic downgrade -1
make generate NAME="add_widget" # alembic revision --autogenerate
make history # alembic history
make run-http # FastAPI + Granian
make run-consumers # FastStream (NATS)
make run-worker # Taskiq worker
make run-scheduler # Taskiq scheduler
make lint # ruff check
make format # ruff format + ruff check --fix
make typecheck # mypy --strict
make check # lint + typecheck
make test # all pytest
make test-unit / test-integration / test-e2e
make docker-dev-up # start dev containers (Postgres, Redis, NATS)
make docker-dev-down # stop them
make docker-dev-rebuild # down + build --no-cache
The canonical walkthrough is in CLAUDE.md. Summary:
database/models/, run make generate NAME="add_widget", inspect the migrationCreate{Entity}Type, Update{Entity}Type, {Entity}Loads in database/types/BaseRepository, add verbs from the fixed vocabulary, return Result[T]DBGateway in database/psql/__init__.py{Entity}Result(Result) in application/v1/results/Request + UseCase in one file under application/v1/usecases/{domain}/; map ORM → Result via {Entity}Result(**orm.as_dict())application/v1/usecases/__init__.py::setup_use_cases()presentation/http/v1/contracts/If you're using Claude Code, the usecase / endpoint / repository / migration / tests skills will walk you through each step with the exact patterns — including the test-coverage scenarios that prevent the classic "returned 200 but the mutation silently dropped a field" gap.
Released under the MIT License — see the LICENSE file for the full text.
Portable skills, agents, and templates that add Spec-Driven Development and TDD workflows to any Claude Code project. De
Visual, example-driven guide with copy-paste CLAUDE.md templates for quick setup
ATLAS: a senior-engineer layer for Claude Code. Explore with wireframes & prototypes, clarify the essentials, capture it
Production-tested CLAUDE.md and rules that make Claude Code write better code and more human text. Anti-AI-slop writing