Course page
Log in

You are watching a free preview. Enroll to open all 26 lessons, track progress and ask the course tutor.

Enroll for $69.99

Section 1: FastAPI fundamentals

Project setup and the first endpoints

Article 12 min Lesson 2 of 26 Preview

Create the project and install dependencies with uv:

uv init taskboard --package
cd taskboard
uv add "fastapi[standard]" "sqlalchemy[asyncio]" asyncpg alembic pydantic-settings
uv add --dev pytest httpx

The fastapi[standard] extra includes Uvicorn, the ASGI server, and the fastapi command line tool.

Project layout

src/taskboard/
  main.py            app creation
  config.py          settings
  db.py              engine and session
  models/            SQLAlchemy models
  schemas/           Pydantic models
  routers/           one module per resource
  services/          business logic
tests/

Separating schemas (what the API accepts and returns) from models (how data is stored) feels like duplication at first. It pays off quickly: you can change the database without breaking the API contract, and you never leak internal fields such as password hashes by accident.

The app

from fastapi import FastAPI
from taskboard.routers import health, projects

app = FastAPI(title="Taskboard API", version="0.1.0")
app.include_router(health.router)
app.include_router(projects.router, prefix="/projects", tags=["projects"])

A health router is a good first endpoint:

from fastapi import APIRouter

router = APIRouter()

@router.get("/health")
async def health() -> dict[str, str]:
    return {"status": "ok"}

Run the development server with auto reload:

uv run fastapi dev src/taskboard/main.py

Open /docs in the browser. FastAPI generated interactive Swagger UI documentation from your code. /openapi.json is the machine readable document behind it.

Settings

Configuration comes from environment variables, validated by pydantic-settings:

from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_file=".env")
    database_url: str
    jwt_secret: str
    debug: bool = False

settings = Settings()

If a required variable is missing, the app fails at startup with a clear message instead of failing later on the first request. Keep a .env.example in the repository and the real .env out of it.

A first resource with fake data

Add a projects router with GET /projects returning a hard coded list, and check it in /docs. In the next lesson we replace the dicts with Pydantic models.

← → switch lessons