Files
claude-engineering-plugin/plugins/compound-engineering/skills/fastapi-style/SKILL.md
John Lamb fedf2ff8e4
Some checks failed
CI / test (push) Has been cancelled
rewrite ruby to python
2026-01-26 14:39:43 -06:00

7.7 KiB

name, description
name description
fastapi-style This skill should be used when writing Python and FastAPI code following opinionated best practices. It applies when building APIs, creating Pydantic models, working with SQLAlchemy, or any FastAPI application. Triggers on FastAPI code generation, API design, refactoring requests, code review, or when discussing async Python patterns. Embodies thin routers, rich Pydantic models, dependency injection, async-first design, and the "explicit is better than implicit" philosophy.
Apply opinionated FastAPI conventions to Python API code. This skill provides comprehensive domain expertise for building maintainable, performant FastAPI applications following established patterns from production codebases.

<essential_principles>

Core Philosophy

"Explicit is better than implicit. Simple is better than complex."

The FastAPI Way:

  • Thin routers, rich Pydantic models with validation
  • Dependency injection for everything
  • Async-first with SQLAlchemy 2.0
  • Type hints everywhere - let the tools help you
  • Settings via pydantic-settings, not raw env vars
  • Database-backed solutions where possible

What to deliberately avoid:

  • Flask patterns (global request context)
  • Django ORM in FastAPI (use SQLAlchemy 2.0)
  • Synchronous database calls (use async)
  • Manual JSON serialization (Pydantic handles it)
  • Global state (use dependency injection)
  • * imports (explicit imports only)
  • Circular imports (proper module structure)

Development Philosophy:

  • Type everything - mypy should pass
  • Fail fast with descriptive errors
  • Write-time validation over read-time checks
  • Database constraints complement Pydantic validation
  • Tests are documentation </essential_principles>
What are you working on?
  1. Routers - Route organization, dependency injection, response models
  2. Models - Pydantic schemas, SQLAlchemy models, validation patterns
  3. Database - SQLAlchemy 2.0 async, Alembic migrations, transactions
  4. Testing - pytest, httpx TestClient, fixtures, async testing
  5. Security - OAuth2, JWT, permissions, CORS, rate limiting
  6. Background Tasks - Celery, ARQ, or FastAPI BackgroundTasks
  7. Code Review - Review code against FastAPI best practices
  8. General Guidance - Philosophy and conventions

Specify a number or describe your task.

Response Reference to Read
1, router, route, endpoint routers.md
2, model, pydantic, schema, sqlalchemy models.md
3, database, db, alembic, migration, transaction database.md
4, test, testing, pytest, fixture testing.md
5, security, auth, oauth, jwt, permission security.md
6, background, task, celery, arq, queue background_tasks.md
7, review Read all references, then review code
8, general task Read relevant references based on context

After reading relevant references, apply patterns to the user's code.

<quick_reference>

Project Structure

app/
├── main.py              # FastAPI app creation, middleware
├── config.py            # Settings via pydantic-settings
├── dependencies.py      # Shared dependencies
├── database.py          # Database session, engine
├── models/              # SQLAlchemy models
│   ├── __init__.py
│   ├── base.py          # Base model class
│   └── user.py
├── schemas/             # Pydantic models
│   ├── __init__.py
│   └── user.py
├── routers/             # API routers
│   ├── __init__.py
│   └── users.py
├── services/            # Business logic (if needed)
├── utils/               # Shared utilities
└── tests/
    ├── conftest.py      # Fixtures
    └── test_users.py

Naming Conventions

Pydantic Schemas:

  • UserCreate - input for creation
  • UserUpdate - input for updates (all fields Optional)
  • UserRead - output representation
  • UserInDB - internal with hashed password

SQLAlchemy Models: Singular nouns (User, Item, Order)

Routers: Plural resource names (users.py, items.py)

Dependencies: Verb phrases (get_current_user, get_db_session)

Type Hints

# Always type function signatures
async def get_user(
    user_id: int,
    db: AsyncSession = Depends(get_db),
) -> User:
    ...

# Use Annotated for dependency injection
from typing import Annotated
CurrentUser = Annotated[User, Depends(get_current_user)]
DBSession = Annotated[AsyncSession, Depends(get_db)]

Response Patterns

# Explicit response_model
@router.get("/users/{user_id}", response_model=UserRead)
async def get_user(user_id: int, db: DBSession) -> User:
    ...

# Status codes
@router.post("/users", status_code=status.HTTP_201_CREATED)
async def create_user(...) -> UserRead:
    ...

# Multiple response types
@router.get("/users/{user_id}", responses={404: {"model": ErrorResponse}})

Error Handling

from fastapi import HTTPException, status

# Specific exceptions
raise HTTPException(
    status_code=status.HTTP_404_NOT_FOUND,
    detail="User not found",
)

# Custom exception handlers
@app.exception_handler(ValidationError)
async def validation_exception_handler(request, exc):
    return JSONResponse(status_code=422, content={"detail": exc.errors()})

Dependency Injection

# Simple dependency
async def get_db() -> AsyncGenerator[AsyncSession, None]:
    async with async_session() as session:
        yield session

# Parameterized dependency
def get_pagination(
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=1000),
) -> dict:
    return {"skip": skip, "limit": limit}

# Class-based dependency
class CommonQueryParams:
    def __init__(self, q: str | None = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit

</quick_reference>

<reference_index>

Domain Knowledge

All detailed patterns in references/:

File Topics
routers.md Route organization, dependency injection, response models, middleware, versioning
models.md Pydantic schemas, SQLAlchemy models, validation, serialization, mixins
database.md SQLAlchemy 2.0 async, Alembic migrations, transactions, connection pooling
testing.md pytest, httpx TestClient, fixtures, async testing, mocking patterns
security.md OAuth2, JWT, permissions, CORS, rate limiting, secrets management
background_tasks.md FastAPI BackgroundTasks, Celery, ARQ, task patterns
</reference_index>

<success_criteria> Code follows FastAPI best practices when:

  • Routers are thin, focused on HTTP concerns only
  • Pydantic models handle all validation and serialization
  • SQLAlchemy 2.0 async patterns used correctly
  • Dependencies injected, not imported as globals
  • Type hints on all function signatures
  • Settings via pydantic-settings
  • Tests use pytest with async support
  • Error handling is explicit and informative
  • Security follows OAuth2/JWT standards
  • Background tasks use appropriate tool for the job </success_criteria>
Based on FastAPI best practices from the official documentation, real-world production patterns, and the Python community's collective wisdom.

Key Resources: