COMPOSE_DEV := docker compose -f docker-compose.dev.yml .DEFAULT_GOAL := help .PHONY: help dev dev-backend dev-frontend down migrate seed types lint eval e2e help: ## list available targets @grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*## "}; {printf " %-10s %s\n", $$1, $$2}' dev: ## full dev stack with hot reload (postgres in docker, backend + frontend native) @for port in 8000 5173; do \ if ss -ltn "sport = :$$port" 2>/dev/null | tail -n +2 | grep -q .; then \ echo "ERROR: port $$port is already in use — stale 'uvicorn app.main:app' or 'vite dev'?"; \ ss -ltnp "sport = :$$port" 2>/dev/null | tail -n +2; \ echo "Kill the shown process and retry."; \ exit 1; \ fi; \ done $(COMPOSE_DEV) up -d --wait $(MAKE) -j2 dev-backend dev-frontend dev-backend: cd backend && uv run uvicorn app.main:app --reload --port 8000 dev-frontend: cd frontend && npm run dev down: ## stop the dev stack $(COMPOSE_DEV) down migrate: ## apply alembic migrations cd backend && uv run alembic upgrade head seed: ## seed dev data cd backend && uv run python -m app.seed types: ## regenerate frontend/src/lib/api/schema.d.ts from the FastAPI OpenAPI schema cd backend && uv run python -c "import json, sys; from app.main import app; json.dump(app.openapi(), sys.stdout)" > ../frontend/openapi.json cd frontend && npx openapi-typescript openapi.json -o src/lib/api/schema.d.ts rm frontend/openapi.json lint: ## ruff + prettier + eslint + design-token contrast check (CI runs the same) cd backend && uv run ruff check . && uv run ruff format --check . @# Recompiling Paraglide rewrites every module under src/lib/paraglide/. A @# running `make dev` is watching exactly those files and ends up serving a @# stale graph (500s until vite restarts) -- and it compiles them through @# its own plugin anyway, so skipping is not a gap. @if ss -ltn 'sport = :5173' 2>/dev/null | tail -n +2 | grep -q .; then \ echo "dev server on :5173 -- keeping its compiled messages, checking files only"; \ cd frontend && npm run lint:files; \ else \ cd frontend && npm run lint; \ fi python3 frontend/scripts/contrast-check.py python3 frontend/scripts/check-messages.py python3 backend/scripts/check-no-ui-strings.py eval: ## LLM eval suite against the configured endpoints cd backend && uv run pytest tests/evals -m eval -s e2e: ## playwright end-to-end tests against the dev stack cd frontend && npm run test:e2e