|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +Full Stack FastAPI Template with React frontend. A production-ready template for building modern web applications with FastAPI backend and React frontend, using Docker Compose for both development and deployment. |
| 8 | + |
| 9 | +**Tech Stack:** |
| 10 | +- Backend: FastAPI, SQLModel (ORM), PostgreSQL, Alembic (migrations), JWT auth |
| 11 | +- Frontend: React 19, TypeScript, Vite, TanStack Query/Router, Tailwind CSS, shadcn/ui |
| 12 | +- Infrastructure: Docker Compose, Traefik (reverse proxy) |
| 13 | +- Testing: Pytest (backend), Playwright (frontend E2E) |
| 14 | + |
| 15 | +## Development Setup |
| 16 | + |
| 17 | +### Starting the Stack |
| 18 | + |
| 19 | +```bash |
| 20 | +# Start full stack with hot reload |
| 21 | +docker compose watch |
| 22 | + |
| 23 | +# View logs |
| 24 | +docker compose logs |
| 25 | +docker compose logs backend # specific service |
| 26 | +``` |
| 27 | + |
| 28 | +**URLs:** |
| 29 | +- Frontend: http://localhost:5173 |
| 30 | +- Backend API: http://localhost:8000 |
| 31 | +- API Docs: http://localhost:8000/docs |
| 32 | +- Adminer (DB): http://localhost:8080 |
| 33 | +- Traefik UI: http://localhost:8090 |
| 34 | +- MailCatcher: http://localhost:1080 |
| 35 | + |
| 36 | +### Local Development (without Docker) |
| 37 | + |
| 38 | +Stop a Docker service and run locally: |
| 39 | + |
| 40 | +```bash |
| 41 | +# Backend |
| 42 | +docker compose stop backend |
| 43 | +cd backend |
| 44 | +fastapi dev app/main.py |
| 45 | + |
| 46 | +# Frontend |
| 47 | +docker compose stop frontend |
| 48 | +cd frontend |
| 49 | +npm run dev |
| 50 | +``` |
| 51 | + |
| 52 | +## Backend Development |
| 53 | + |
| 54 | +**Location:** `backend/app/` |
| 55 | + |
| 56 | +### Common Commands |
| 57 | + |
| 58 | +```bash |
| 59 | +cd backend |
| 60 | + |
| 61 | +# Install dependencies |
| 62 | +uv sync |
| 63 | + |
| 64 | +# Activate virtual environment |
| 65 | +source .venv/bin/activate |
| 66 | + |
| 67 | +# Run tests with coverage |
| 68 | +bash scripts/test.sh |
| 69 | + |
| 70 | +# Run tests if stack is running |
| 71 | +docker compose exec backend bash scripts/tests-start.sh |
| 72 | + |
| 73 | +# Run tests with extra args (e.g., stop on first error) |
| 74 | +docker compose exec backend bash scripts/tests-start.sh -x |
| 75 | + |
| 76 | +# Format code |
| 77 | +bash scripts/format.sh |
| 78 | + |
| 79 | +# Lint code |
| 80 | +bash scripts/lint.sh |
| 81 | + |
| 82 | +# Run pre-commit hooks manually |
| 83 | +uv run prek run --all-files |
| 84 | +``` |
| 85 | + |
| 86 | +### Database Migrations |
| 87 | + |
| 88 | +Use Alembic for all schema changes: |
| 89 | + |
| 90 | +```bash |
| 91 | +# Enter backend container |
| 92 | +docker compose exec backend bash |
| 93 | + |
| 94 | +# Create migration after model changes |
| 95 | +alembic revision --autogenerate -m "Description of change" |
| 96 | + |
| 97 | +# Apply migrations |
| 98 | +alembic upgrade head |
| 99 | +``` |
| 100 | + |
| 101 | +**Important:** Always create migrations when modifying models in `backend/app/models.py`. The application expects the database schema to match the models. |
| 102 | + |
| 103 | +### Architecture |
| 104 | + |
| 105 | +**Key Files:** |
| 106 | +- `app/main.py` - FastAPI app initialization, CORS, Sentry |
| 107 | +- `app/models.py` - SQLModel models (User, Item) with both ORM and Pydantic schemas |
| 108 | +- `app/crud.py` - Database operations (create, read, update, delete) |
| 109 | +- `app/api/main.py` - API router setup |
| 110 | +- `app/api/routes/` - API endpoints organized by resource |
| 111 | +- `app/api/deps.py` - FastAPI dependencies (DB session, auth, user injection) |
| 112 | +- `app/core/config.py` - Settings management with Pydantic |
| 113 | +- `app/core/security.py` - Password hashing, JWT token creation/validation |
| 114 | +- `app/core/db.py` - Database engine and session setup |
| 115 | + |
| 116 | +**Dependency Injection Pattern:** |
| 117 | +- `SessionDep` - SQLModel database session |
| 118 | +- `CurrentUser` - Authenticated user from JWT token |
| 119 | +- `get_current_active_superuser` - Admin-only endpoints |
| 120 | + |
| 121 | +**Model Pattern:** |
| 122 | +SQLModel models use inheritance for different contexts: |
| 123 | +- `Base` classes: Shared fields |
| 124 | +- `Create` classes: API input for creation |
| 125 | +- `Update` classes: API input for updates (optional fields) |
| 126 | +- `Public` classes: API output (excludes sensitive fields) |
| 127 | +- Table classes: Database models (e.g., `User(UserBase, table=True)`) |
| 128 | + |
| 129 | +### Testing |
| 130 | + |
| 131 | +Tests are in `backend/tests/`. Use pytest fixtures for database setup. Coverage reports are in `htmlcov/index.html`. |
| 132 | + |
| 133 | +## Frontend Development |
| 134 | + |
| 135 | +**Location:** `frontend/src/` |
| 136 | + |
| 137 | +### Common Commands |
| 138 | + |
| 139 | +```bash |
| 140 | +cd frontend |
| 141 | + |
| 142 | +# Install Node.js version (using fnm or nvm) |
| 143 | +fnm install && fnm use |
| 144 | + |
| 145 | +# Install dependencies |
| 146 | +npm install |
| 147 | + |
| 148 | +# Start dev server |
| 149 | +npm run dev |
| 150 | + |
| 151 | +# Build for production |
| 152 | +npm run build |
| 153 | + |
| 154 | +# Lint and format with Biome |
| 155 | +npm run lint |
| 156 | + |
| 157 | +# Run E2E tests |
| 158 | +npx playwright test |
| 159 | + |
| 160 | +# Run E2E tests in UI mode |
| 161 | +npx playwright test --ui |
| 162 | +``` |
| 163 | + |
| 164 | +### Generate Client |
| 165 | + |
| 166 | +When backend OpenAPI schema changes, regenerate the frontend client: |
| 167 | + |
| 168 | +```bash |
| 169 | +# Automatic (requires backend venv activated) |
| 170 | +./scripts/generate-client.sh |
| 171 | + |
| 172 | +# Manual |
| 173 | +# 1. Start Docker stack |
| 174 | +# 2. Download http://localhost:8000/api/v1/openapi.json to frontend/openapi.json |
| 175 | +# 3. cd frontend && npm run generate-client |
| 176 | +``` |
| 177 | + |
| 178 | +**Important:** Regenerate after any backend API changes. |
| 179 | + |
| 180 | +### Architecture |
| 181 | + |
| 182 | +**Key Directories:** |
| 183 | +- `src/routes/` - TanStack Router file-based routing with route components |
| 184 | +- `src/components/` - Reusable React components |
| 185 | +- `src/client/` - Auto-generated OpenAPI client (DO NOT EDIT) |
| 186 | +- `src/hooks/` - Custom React hooks |
| 187 | +- `src/assets/` - Static assets |
| 188 | + |
| 189 | +**Routing:** |
| 190 | +Uses TanStack Router with file-based routing: |
| 191 | +- `__root.tsx` - Root layout |
| 192 | +- `_layout.tsx` - Protected routes layout |
| 193 | +- `_layout/index.tsx`, `_layout/items.tsx`, etc. - Protected pages |
| 194 | +- `login.tsx`, `signup.tsx` - Public routes |
| 195 | + |
| 196 | +**State Management:** |
| 197 | +- TanStack Query for server state |
| 198 | +- React Context for auth state |
| 199 | +- Form state with react-hook-form + Zod validation |
| 200 | + |
| 201 | +**Styling:** |
| 202 | +Tailwind CSS with shadcn/ui components. Dark mode support via next-themes. |
| 203 | + |
| 204 | +## Code Quality |
| 205 | + |
| 206 | +### Pre-commit Hooks |
| 207 | + |
| 208 | +Install `prek` (modern pre-commit alternative) to run linting/formatting before commits: |
| 209 | + |
| 210 | +```bash |
| 211 | +cd backend |
| 212 | +uv run prek install -f |
| 213 | +``` |
| 214 | + |
| 215 | +Hooks run automatically on `git commit`. Manual run: |
| 216 | + |
| 217 | +```bash |
| 218 | +cd backend |
| 219 | +uv run prek run --all-files |
| 220 | +``` |
| 221 | + |
| 222 | +**Configured Checks:** |
| 223 | +- Ruff (Python linting and formatting) |
| 224 | +- Biome (TypeScript/JavaScript linting and formatting) |
| 225 | +- File checks (TOML, YAML, trailing whitespace, etc.) |
| 226 | + |
| 227 | +## Environment Variables |
| 228 | + |
| 229 | +Edit `.env` file for configuration. **Must change before deployment:** |
| 230 | +- `SECRET_KEY` - JWT signing key |
| 231 | +- `FIRST_SUPERUSER_PASSWORD` - Admin password |
| 232 | +- `POSTGRES_PASSWORD` - Database password |
| 233 | + |
| 234 | +Generate secure keys: |
| 235 | + |
| 236 | +```bash |
| 237 | +python -c "import secrets; print(secrets.token_urlsafe(32))" |
| 238 | +``` |
| 239 | + |
| 240 | +## Testing with Custom Domains |
| 241 | + |
| 242 | +For subdomain testing locally, use `localhost.tiangolo.com` (resolves to 127.0.0.1): |
| 243 | + |
| 244 | +```bash |
| 245 | +# Edit .env |
| 246 | +DOMAIN=localhost.tiangolo.com |
| 247 | + |
| 248 | +# Restart |
| 249 | +docker compose watch |
| 250 | +``` |
| 251 | + |
| 252 | +Access via: |
| 253 | +- Frontend: http://dashboard.localhost.tiangolo.com |
| 254 | +- Backend: http://api.localhost.tiangolo.com |
| 255 | + |
| 256 | +## Deployment |
| 257 | + |
| 258 | +See `deployment.md` for full deployment instructions. Quick overview: |
| 259 | + |
| 260 | +```bash |
| 261 | +# Build images |
| 262 | +bash scripts/build.sh |
| 263 | + |
| 264 | +# Build and push to registry |
| 265 | +bash scripts/build-push.sh |
| 266 | + |
| 267 | +# Deploy to server |
| 268 | +bash scripts/deploy.sh |
| 269 | +``` |
| 270 | + |
| 271 | +## Authentication Flow |
| 272 | + |
| 273 | +1. User logs in via `/api/v1/login/access-token` with email/password |
| 274 | +2. Backend validates credentials, returns JWT access token |
| 275 | +3. Frontend stores token, includes in Authorization header |
| 276 | +4. Backend validates JWT on protected routes via `get_current_user` dependency |
| 277 | +5. User info injected into endpoint via `CurrentUser` dependency |
| 278 | + |
| 279 | +## Key Patterns |
| 280 | + |
| 281 | +**Backend:** |
| 282 | +- Use `SessionDep` for database access in endpoints |
| 283 | +- Use `CurrentUser` for authenticated user |
| 284 | +- Create/update operations return full model objects |
| 285 | +- All models use UUID primary keys |
| 286 | +- Password hashing via passlib with bcrypt |
| 287 | + |
| 288 | +**Frontend:** |
| 289 | +- Use TanStack Query hooks for API calls |
| 290 | +- Use generated client from `src/client/` for type-safe API calls |
| 291 | +- Forms use react-hook-form with Zod schemas |
| 292 | +- Protected routes check auth in layout |
| 293 | +- Error boundaries for error handling |
0 commit comments