FastAPI service
Layout
api/
app/
__init__.py
main.py # FastAPI() + middleware + router include
config.py # pydantic-settings Settings
database.py # SQLAlchemy engine, SessionLocal, get_db, Base
models.py # SQLAlchemy ORM models
schemas.py # Pydantic request/response schemas
routers/<resource>.py
migrations/ # Alembic
requirements.txt
.env # local-only, not committed
.env.example # committed template
.venv/ # local-only, not committed
Virtual environment (required)
cd api
python3 -m venv .venv # use /opt/homebrew/bin/python3.12 if system python < 3.10
source .venv/bin/activate
pip install -r requirements.txt
Never pip install without the venv active. Never install deps globally.
Running
source api/.venv/bin/activate
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
Database & migrations
- Configuration comes from environment variables (
DATABASE_URL, etc.) loaded viaSettingsinapp/config.py. - Schema changes are always Alembic migrations — never raw DDL, never SQLAlchemy
create_allin app code. - Create a migration with
alembic revision --autogenerate -m "<message>", review the generated file, thenalembic upgrade head.
Endpoints
- Declare routes on an
APIRouter(prefix="/<resource>", tags=["<resource>"])inapp/routers/<resource>.py. - Use
response_model=so OpenAPI stays accurate. - Inject DB sessions via
Depends(get_db); never reach forSessionLocal()in handlers. - Raise
HTTPExceptionwith explicitstatus_codefor error paths.
Validation
- Pydantic schemas in
schemas.pyare the source of truth for shape + validation. - Enums (e.g.
Condition) live asstr, Enumclasses so they render as string enums in OpenAPI.
CORS
- Allowed origins are driven by
CORS_ALLOW_ORIGINSin.env(comma-separated) and applied inmain.py.
Source: gmoore-al/hamstr — distributed by TomeVault.