fastapi-blueprint
Production-ready FastAPI template — zero-boilerplate CRUD, auto domain discovery, AI-native development with 12 Claude Code skills
FastAPI Blueprint
Production-ready FastAPI backend blueprint.
Inherit one base class, get 7 CRUD endpoints. Add a domain, it registers itself.
Designed for teams of 5+ developers managing 10+ domains.
Quick Start · Architecture · AI-Native Development · Comparison · 한국어
Key Features
- Zero-boilerplate CRUD -- Inherit
BaseRepository[DTO]+BaseService[DTO], get 7 async CRUD methods instantly - Auto domain discovery -- Add a domain folder, it auto-registers. No container or bootstrap changes needed
- 4 interface types -- HTTP API (FastAPI) + Async Worker (Taskiq) + Admin UI (SQLAdmin) + MCP Server (planned)
- Architecture enforcement -- Pre-commit hooks block
Domain -> Infrastructureimports at commit time - Type-safe generics --
BaseRepository[ProductDTO],BaseService[ProductDTO],SuccessResponse[ProductResponse] - DDD layered structure -- Each domain is fully independent with its own layers (Domain / Infrastructure / Interface / Application)
- 12 AI development skills -- Claude Code slash commands for scaffolding, testing, architecture review, and more
- 14 Architecture Decision Records -- Every major design choice documented with rationale
Why?
# Before: Repeat the same CRUD for every domain
@router.post("/user")
async def create_user(user: UserCreate):
db = get_db()
new_user = User(**user.dict())
db.add(new_user)
db.commit()
return new_user
@router.post("/product") # Repeat again...
async def create_product(product: ProductCreate):
db = get_db()
new_product = Product(**product.dict())
db.add(new_product)
db.commit()
return new_product
# After: One inheritance line, CRUD done
class ProductRepository(BaseRepository[ProductDTO]):
def __init__(self, database: Database):
super().__init__(database=database, model=ProductModel, return_entity=ProductDTO)
class ProductService(BaseService[ProductDTO]):
def __init__(self, product_repository: ProductRepositoryProtocol):
super().__init__(repository=product_repository)
# 7 CRUD methods provided automatically -- just add your custom logic
Architecture
Router -> Service(BaseService) -> Repository(BaseRepository) -> DB
^ Simple CRUD: this is all you need
Router -> UseCase -> Service -> Repository -> DB
^ Add only when complex business logic is required
Layer Responsibilities
| Layer | Role | Base Class |
|---|---|---|
| Interface | Router, Request/Response, Admin, Worker Task | - |
| Domain | Service (business logic), Protocol, DTO, Event | BaseService[ReturnDTO] |
| Infrastructure | Repository (DB access), Model, DI Container | BaseRepository[ReturnDTO] |
| Application | UseCase (orchestration) -- optional | - |
Data Flow
Write: Request --> Service --> Repository --> Model -> DB
Read: Response <-- Service <-- Repository <-- DTO <-- Model
- Request is passed directly to Service (no extra conversion needed)
- Repository handles Model -> DTO conversion (
model_validate(model, from_attributes=True)) - Router handles DTO -> Response conversion (
Response(**dto.model_dump(exclude={...})))
Data Objects
| Object | Role | Location |
|---|---|---|
| Request/Response | API contract | interface/server/dtos/ |
| DTO | Internal data transfer between layers | domain/dtos/ |
| Model | DB table mapping (never exposed outside Repository) | infrastructure/database/models/ |
AI-Native Development (AIDD)
This template works great on its own. With Claude Code, it's magic.
Zero Learning Curve
Complex architecture? Type /onboard -- it explains everything at your level.
The /onboard skill adapts to your experience:
- Beginner: Explains DDD concepts with simple analogies
- Intermediate: Focuses on this project's specific patterns
- Advanced: Jumps straight to architecture rules and conventions
12 Built-in Skills
| Command | What it does |
|---|---|
/onboard |
Interactive onboarding -- adapts to your experience level |
/new-domain {name} |
Scaffold an entire domain (21+ source files + tests) |
/add-api {description} |
Add API endpoint to existing domain |
/add-worker-task {domain} {task} |
Add async Taskiq background task |
/add-cross-domain from:{a} to:{b} |
Wire cross-domain dependency via Protocol DIP |
/plan-feature {description} |
Requirements interview -> architecture -> security -> task breakdown |
/review-architecture {domain} |
Architecture compliance audit (20+ checks) |
/security-review {domain} |
OWASP-based security audit |
/test-domain {domain} |
Generate or run domain tests |
/fix-bug {description} |
Structured bug fixing workflow |
/sync-guidelines |
Sync docs after design changes |
/migrate-domain {command} |
Alembic migration management |
MCP Server Setup
To use AIDD features, configure these MCP servers:
Serena -- Symbolic code navigation/editing (LSP-level rename, reference analysis)
{
"mcpServers": {
"serena": {
"command": "uvx",
"args": ["--from", "serena-mcp", "serena", "--project-root", "."]
}
}
}
context7 -- Up-to-date library documentation
{
"mcpServers": {
"context7": {
"command": "npx",
"args": ["-y", "@upstash/context7-mcp@latest"]
}
}
}
The project works without MCP servers. AIDD skills require MCP server configuration.
Quick Start
# 1. Clone
git clone https://github.com/Mr-DooSun/fastapi-blueprint.git
cd fastapi-blueprint
# 2. Setup (requires uv)
make setup
# 3. Set up environment variables
cp _env/local.env.example _env/local.env
# 4. Start PostgreSQL + run migrations + start server
make dev
Open http://localhost:8000/docs-swagger to explore the API.
Manual setup (without Make)# 2. Create virtual environment + install dependencies
uv venv --python 3.12
source .venv/bin/activate
uv sync --group dev
# 3. Set up environment variables
cp _env/local.env.example _env/local.env
# 4. Start PostgreSQL (Docker)
docker compose -f docker-compose.local.yml up -d postgres
# 5. Run migrations + start server
alembic upgrade head
python run_server_local.py --env local
Adding a New Domain
Using Product domain as an example:
1. Domain Layer
# src/product/domain/dtos/product_dto.py
class ProductDTO(BaseModel):
id: int = Field(..., description="Product ID")
name: str = Field(..., description="Product name")
price: int = Field(..., description="Price")
created_at: datetime
updated_at: datetime
# src/product/domain/protocols/product_repository_protocol.py
class ProductRepositoryProtocol(BaseRepositoryProtocol[ProductDTO]):
pass
# src/product/domain/services/product_service.py
class ProductService(BaseService[ProductDTO]):
def __init__(self, product_repository: ProductRepositoryProtocol):
super().__init__(repository=product_repository)
# CRUD provided automatically. Just add custom logic.
2. Infrastructure Layer
# src/product/infrastructure/database/models/product_model.py
class ProductModel(Base):
__tablename__ = "product"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
price: Mapped[int] = mapped_column(Integer, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(DateTime, onupdate=func.now())
# src/product/infrastructure/repositories/product_repository.py
class ProductRepository(BaseRepository[ProductDTO]):
def __init__(self, database: Database):
super().__init__(database=database, model=ProductModel, return_entity=ProductDTO)
# src/product/infrastructure/di/product_container.py
class ProductContainer(containers.DeclarativeContainer):
core_container = providers.DependenciesContainer()
product_repository = providers.Singleton(ProductRepository, database=core_container.database)
product_service = providers.Factory(ProductService, product_repository=product_repository)
3. Interface Layer
# src/product/interface/server/routers/product_router.py
@router.post("/product", response_model=SuccessResponse[ProductResponse])
@inject
async def create_product(
item: CreateProductRequest,
product_service: ProductService = Depends(Provide[ProductContainer.product_service]),
) -> SuccessResponse[ProductResponse]:
data = await product_service.create_data(entity=item)
return SuccessResponse(data=ProductResponse(**data.model_dump()))
Auto Registration
discover_domains() automatically detects new domains.
No changes needed in _apps/ containers or bootstrap files.
Discovery conditions:
src/{name}/__init__.pyexistssrc/{name}/infrastructure/di/{name}_container.pyexists
With Claude Code, just run
/new-domain productto scaffold all of this automatically.
4 Interface Types
Each domain can expose functionality through multiple interfaces:
| Interface | Technology | Location | Purpose |
|---|---|---|---|
| HTTP API | FastAPI | interface/server/ |
REST API endpoints |
| Async Worker | Taskiq + SQS | interface/worker/ |
Background task processing |
| Admin UI | SQLAdmin | interface/admin/ |
Database management dashboard |
| MCP Server | FastMCP | interface/mcp/ |
AI tool integration (planned) |
All interfaces share the same Domain and Infrastructure layers -- write your business logic once, expose it everywhere.
Tech Stack
Core
| Technology | Purpose |
|---|---|
| FastAPI | Async web framework |
| Pydantic 2.x | Data validation & settings |
| SQLAlchemy 2.0 | Async ORM |
| dependency-injector | IoC Container (why?) |
Infrastructure
| Technology | Purpose |
|---|---|
| PostgreSQL + asyncpg | Primary RDBMS |
| Taskiq + AWS SQS | Async task queue (why not Celery?) |
| aiohttp | Async HTTP client |
| aioboto3 | S3/MinIO storage |
| Alembic | DB migrations |
DevOps
| Technology | Purpose |
|---|---|
| Ruff | Linting + formatting (replaces 6 tools) |
| pre-commit | Git hook automation + architecture enforcement |
| UV | Python package management (why not Poetry?) |
| SQLAdmin | DB admin UI |
Project Structure
src/
├── _apps/ # App entry points
│ ├── server/ # FastAPI HTTP server
│ ├── worker/ # Taskiq async worker
│ └── admin/ # SQLAdmin dashboard
│
├── _core/ # Shared infrastructure
│ ├── domain/
│ │ ├── protocols/ # BaseRepositoryProtocol[ReturnDTO]
│ │ └── services/ # BaseService[ReturnDTO]
│ ├── infrastructure/
│ │ ├── database/ # Database, BaseRepository[ReturnDTO]
│ │ ├── http/ # HttpClient, BaseHttpGateway
│ │ ├── taskiq/ # SQS Broker, TaskiqManager
│ │ ├── storage/ # S3/MinIO
│ │ ├── di/ # CoreContainer
│ │ └── discovery.py # Auto domain discovery
│ ├── application/dtos/ # BaseRequest, BaseResponse, SuccessResponse
│ ├── middleware/ # ExceptionMiddleware
│ └── config.py # Settings (pydantic-settings)
│
├── user/ # Example domain
│ ├── domain/
│ │ ├── dtos/ # UserDTO
│ │ ├── protocols/ # UserRepositoryProtocol
│ │ ├── services/ # UserService(BaseService[UserDTO])
│ │ ├── exceptions/ # UserNotFoundException
│ │ └── events/ # UserCreated, UserUpdated
│ ├── infrastructure/
│ │ ├── database/models/ # UserModel
│ │ ├── repositories/ # UserRepository(BaseRepository[UserDTO])
│ │ └── di/ # UserContainer
│ └── interface/
│ ├── server/ # routers/, dtos/, bootstrap/
│ ├── worker/ # tasks/, bootstrap/
│ └── admin/ # SQLAdmin views
│
├── migrations/ # Alembic
├── _env/ # Environment variables
└── docs/history/ # Architecture Decision Records
Comparison
| Feature | FastAPI Blueprint | tiangolo/full-stack | s3rius/template | teamhide/boilerplate |
|---|---|---|---|---|
| Zero-boilerplate CRUD (7 methods) | Yes | No | No | No |
| Auto domain discovery | Yes | No | No | No |
| Architecture enforcement (pre-commit) | Yes | No | No | No |
| AI development skills | 12 | 0 | 0 | 0 |
Adaptive onboarding (/onboard) |
Yes | No | No | No |
| Multi-interface (API+Worker+Admin) | 4 types | 2 | 1 | 1 |
| Architecture Decision Records | 14 | 0 | 0 | 0 |
| Type-safe generics across layers | Yes | Partial | Partial | No |
| DI with IoC Container | Yes | No | No | No |
Architecture Decisions
Every technical choice in this project is documented as an ADR (Architecture Decision Record).
| # | Title |
|---|---|
| 004 | DTO/Entity responsibility redefined |
| 006 | Domain-driven layered architecture |
| 007 | DI container hierarchy and app separation |
| 011 | 3-Tier hybrid architecture |
| 012 | Ruff adoption |
| 013 | Why IoC Container over inheritance |
Roadmap
- JWT Authentication domain
- Product example domain (cross-domain demo)
- Structured logging (structlog)
- FastMCP interface
- Reflex Admin dashboard
- Health check endpoint
- One-click deploy (Railway / Render)
- MkDocs documentation site
Star this repo to follow our progress!
Contributing
See CONTRIBUTING.md for development setup, coding guidelines, and PR process.
License
MIT License -- Free for commercial use, modification, and distribution.
Star History
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found