UXDL Docs

Folder Structure

Standard FastAPI layout — routers, dependencies, services, and schemas.

Every FastAPI service follows the same layout. It maps one-to-one onto the Express structure so engineers can move between Node and Python services without relearning where things live.

Project layout

plaintext
backend-api/
├── app/
│   ├── main.py                # Entry point — create_app() + FastAPI instance
│   │
│   ├── api/                   # Route definitions (thin — delegate to services)
│   │   ├── deps.py            # Shared dependencies (auth, db session)
│   │   └── v1/
│   │       ├── __init__.py    # api_router — includes all v1 routers
│   │       ├── users.py
│   │       └── projects.py
│   │
│   ├── services/              # Business logic (no FastAPI imports here)
│   │   ├── users.py
│   │   ├── projects.py
│   │   ├── push.py            # FCM send helpers
│   │   ├── uploads.py         # S3 presigned URLs
│   │   └── email/             # Email provider adapters
│   │       ├── __init__.py    # Factory (ses | sendgrid | brevo)
│   │       ├── ses.py
│   │       ├── sendgrid.py
│   │       └── brevo.py
│   │
│   ├── middleware/            # ASGI middleware & exception handlers
│   │   ├── errors.py
│   │   └── rate_limit.py
│   │
│   ├── models/                # SQLAlchemy ORM models
│   │   └── user.py
│   │
│   ├── schemas/               # Pydantic request/response models
│   │   ├── users.py
│   │   └── projects.py
│   │
│   ├── db/                    # Database config & session factory
│   │   ├── session.py         # Async engine + session maker
│   │   └── migrations/        # Alembic migrations
│   │
│   ├── core/                  # Cross-cutting config & security
│   │   ├── config.py          # Pydantic settings
│   │   ├── security.py        # Cognito JWT verification
│   │   └── logging.py
│   │
│   └── lib/                   # Shared clients
│       ├── supabase.py
│       ├── s3.py
│       └── fcm.py

├── tests/
│   ├── unit/
│   └── integration/

├── .env.example
├── docker-compose.yml
├── Dockerfile
├── pyproject.toml
└── uv.lock

Layer responsibilities

LayerResponsibilityMust NOT
api/v1/Define paths, declare dependencies, call serviceContain business logic
api/deps.pyAuth, db session, pagination as Depends()Call the database directly
schemas/Pydantic validation & serializationHold business rules
services/Business logic, orchestrationImport fastapi / Request
models/ · db/SQLAlchemy models, session managementHandle HTTP concerns

Router example

python
# app/api/v1/projects.py
from fastapi import APIRouter, Depends
 
from app.api.deps import CurrentUser, require_scope
from app.schemas.projects import ProjectCreate, ProjectOut
from app.services import projects as projects_service
 
router = APIRouter(prefix="/projects", tags=["projects"])
 
 
@router.get("", response_model=list[ProjectOut])
async def list_projects(user: CurrentUser):
    return await projects_service.list_by_user(user.sub)
 
 
@router.post("", response_model=ProjectOut, status_code=201)
async def create_project(
    payload: ProjectCreate,
    user: CurrentUser,
    _: None = Depends(require_scope("write:projects")),
):
    return await projects_service.create(user.sub, payload)

Schema example

python
# app/schemas/projects.py
from datetime import datetime
from pydantic import BaseModel
 
 
class ProjectCreate(BaseModel):
    name: str
    description: str | None = None
 
 
class ProjectOut(BaseModel):
    id: str
    name: str
    owner_id: str
    created_at: datetime
 
    model_config = {"from_attributes": True}

Service example

python
# app/services/projects.py
from sqlalchemy import select
 
from app.db.session import async_session
from app.models.project import Project
 
 
async def list_by_user(user_id: str) -> list[Project]:
    async with async_session() as session:
        result = await session.execute(
            select(Project).where(Project.owner_id == user_id)
        )
        return list(result.scalars().all())

Naming conventions

ItemConventionExample
Routers{resource}.py in api/v1/users.py
Services{resource}.py in services/users.py
Schemas{resource}.py in schemas/users.py
ORM modelssingular {resource}.py in models/user.py
Modules / functionssnake_caselist_by_user