# Fastapi Project Structure

> Standard directory layout and module organization for FastAPI applications Use when this capability is needed.

- Skill: `tomevault-io/fastapi-project-structure` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/fastapi-project-structure`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/fastapi-project-structure/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/fastapi-project-structure

---


# FastAPI Project Structure

## Standard Layout

```
project/
  app/
    __init__.py
    main.py              # FastAPI app instance and lifespan
    config.py            # Settings via pydantic-settings
    api/
      __init__.py
      v1/
        __init__.py
        router.py        # Aggregates all v1 routers
        endpoints/
          __init__.py
          users.py
          items.py
    models/
      __init__.py
      user.py            # SQLAlchemy / ORM models
      item.py
    schemas/
      __init__.py
      user.py            # Pydantic request/response schemas
      item.py
    deps/
      __init__.py
      database.py        # DB session dependency
      auth.py            # Auth dependencies
    services/
      __init__.py
      user_service.py    # Business logic
      item_service.py
    db/
      __init__.py
      session.py         # Engine and session factory
      base.py            # Declarative base
  tests/
    __init__.py
    conftest.py
    test_users.py
    test_items.py
  alembic/               # Database migrations
    versions/
    env.py
  alembic.ini
  pyproject.toml
```

## Key Conventions

### `app/main.py` -- Application entry point

```python
from contextlib import asynccontextmanager
from fastapi import FastAPI
from app.api.v1.router import api_router
from app.db.session import engine

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup: create tables, init connections
    yield
    # Shutdown: close connections
    await engine.dispose()

app = FastAPI(title="My API", version="1.0.0", lifespan=lifespan)
app.include_router(api_router, prefix="/api/v1")
```

### `app/api/v1/router.py` -- Aggregate routers

```python
from fastapi import APIRouter
from app.api.v1.endpoints import users, items

api_router = APIRouter()
api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(items.router, prefix="/items", tags=["items"])
```

### `app/models/` vs `app/schemas/`

- **models/**: ORM models (SQLAlchemy). Represent database tables.
- **schemas/**: Pydantic models. Represent API request/response shapes.

Keep them separate. Never return an ORM model directly from an endpoint.

### `app/deps/` -- Dependency injection

Place reusable dependencies here. Common patterns:

```python
# app/deps/database.py
from collections.abc import AsyncGenerator
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.session import async_session_maker

async def get_db() -> AsyncGenerator[AsyncSession, None]:
    async with async_session_maker() as session:
        yield session
```

### `app/services/` -- Business logic

Endpoints should be thin. Move logic into service functions:

```python
# app/services/user_service.py
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.user import User

async def get_user_by_id(db: AsyncSession, user_id: int) -> User | None:
    return await db.get(User, user_id)
```

### `app/config.py` -- Settings

```python
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    database_url: str
    secret_key: str
    debug: bool = False

    model_config = {"env_file": ".env"}

settings = Settings()
```

## Rules

1. One router file per resource (users.py, items.py, etc.).
2. Never put business logic in endpoint functions. Use services.
3. Always version your API (`/api/v1/`, `/api/v2/`).
4. Use `Depends()` for all shared state (db sessions, auth, settings).
5. Keep Pydantic schemas and ORM models in separate directories.

---
> Source: [ag2ai/resource-hub](https://github.com/ag2ai/resource-hub) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-16 -->

