Folder Structure
cms-api/
├── app/
│ ├── main.py # FastAPI app, CORS, router registration
│ ├── api/
│ │ └── v1/
│ │ ├── router.py # Aggregates all routers
│ │ ├── auth.py # /auth endpoints
│ │ ├── users.py # /users endpoints
│ │ ├── roles.py # /roles endpoints
│ │ └── permissions.py # /permissions endpoints
│ ├── core/
│ │ ├── config.py # Pydantic settings, .env parsing
│ │ ├── database.py # Engine, SessionLocal, get_db()
│ │ ├── security.py # Password hashing, JWT encode/decode
│ │ ├── dependencies.py # get_current_user, require_permission
│ │ └── exceptions.py # Custom HTTP exceptions
│ ├── models/
│ │ ├── base.py # Base, UUIDMixin, TimestampMixin, SoftDeleteMixin
│ │ ├── user_roles.py # Pivot table: users ↔ roles
│ │ ├── role_permissions.py # Pivot table: roles ↔ permissions
│ │ ├── user.py # User model
│ │ ├── role.py # Role model
│ │ ├── permission.py # Permission model
│ │ └── refresh_token.py # RefreshToken model
│ ├── schemas/
│ │ ├── base.py # BaseSchema, UUIDSchema, TimestampSchema
│ │ ├── user.py # UserCreate, UserUpdate, UserResponse...
│ │ ├── role.py # RoleCreate, RoleUpdate, RoleResponse...
│ │ ├── permission.py # PermissionCreate, PermissionUpdate...
│ │ └── auth.py # LoginRequest, TokenResponse, LoginResponse
│ ├── services/
│ │ ├── auth_service.py # register, login, refresh, logout
│ │ ├── user_service.py # CRUD, password change, role assignment
│ │ ├── role_service.py # CRUD, permission management
│ │ └── permission_service.py # CRUD
│ └── repositories/
│ ├── base.py # BaseRepository with common CRUD
│ ├── user_repository.py
│ ├── role_repository.py
│ ├── permission_repository.py
│ └── refresh_token_repository.py
├── alembic/
│ ├── env.py # Alembic environment config
│ ├── script.py.mako # Migration template
│ └── versions/ # Generated migration files
├── docs/ # MkDocs documentation
├── .env # Local environment (never commit)
├── .env.example # Template for .env
├── alembic.ini # Alembic configuration
├── docker-compose.yml
├── Dockerfile
├── mkdocs.yml
└── requirements.txt
Key Conventions
Naming — files are snake_case, classes are PascalCase, constants are UPPER_CASE.
Imports — every folder has an __init__.py that exports all classes. Always import from the package, not directly from the file where possible.
One responsibility — every file does one thing. Routers contain no logic, services contain no SQL queries, repositories contain no business decisions.
Versioned API — all routes are under /api/v1/. When a breaking change is introduced, /api/v2/ is added without removing v1.