A delivery management platform for Food4Kids, supporting admin and driver workflows.
| Layer | Technology |
|---|---|
| Frontend | React 19, TypeScript, Vite, Tailwind CSS v4, React Router v7 |
| Backend | Python, FastAPI, SQLModel |
| Database | PostgreSQL + Alembic migrations |
| Auth | Firebase Auth |
| Infrastructure | Docker & Docker Compose |
| Package manager | pnpm |
food4kids/
├── backend/python/
│ ├── app/
│ │ ├── dependencies/ # Dependency injection (auth, etc.)
│ │ ├── migrations/ # Alembic database migrations
│ │ ├── models/ # SQLModel database models
│ │ ├── routers/ # FastAPI route handlers
│ │ ├── schemas/ # Pydantic schemas for API
│ │ ├── services/ # Business logic layer
│ │ ├── templates/ # Email HTML (generated — see "Email Templates")
│ │ └── utilities/ # Shared utility functions
│ ├── scripts/ # Developer scripts (run manually, not by CI)
│ ├── tests/ # Unit and functional tests
│ └── server.py # Application entry point
├── frontend/ # React + TypeScript frontend (see frontend/README.md)
├── db-init/ # Database initialization scripts
├── docker-compose.yml
└── README.md
- Docker Desktop installed and running
git clone git@github.com:uwblueprint/food4kids.git
cd food4kidsYou need two env files: .env (backend) and frontend/.env (frontend). Never commit these files.
The backend .env is stored in Google Secret Manager and pulled via a script. For the frontend, copy the frontend/.env.example template to frontend/.env. It currently holds a single variable, VITE_API_BASE_URL (the backend API URL, defaulting to http://localhost:8080).
Prerequisites: Google Cloud CLI installed.
1. Get the service account credentials
Download the food4kids-env-service-account.json file from the Food4Kids Developers shared Google Drive in UW Blueprint. Save it to the repo root (it is gitignored automatically).
2. Authenticate with the service account
gcloud auth activate-service-account --key-file=food4kids-env-service-account.json3. Run the pull script
Mac/Linux:
chmod +x pull-env.sh # only needed once
./pull-env.shWindows (Git Bash or WSL):
bash pull-env.shWindows (PowerShell, if you don't have Git Bash/WSL):
$env:GOOGLE_APPLICATION_CREDENTIALS = "food4kids-env-service-account.json"
gcloud secrets versions access latest --secret="f4k-development-backend-env" --project="food4kids-473501" | Out-File -Encoding utf8 .envThis writes .env to the repo root. You still need frontend/.env from the PL.
The repo ships a pre-commit hook that keeps the frontend OpenAPI client in sync with the backend automatically — when a commit touches the API contract it regenerates frontend/openapi.json and frontend/src/api/generated/ (no running backend needed) and stages the result.
It enables itself the first time you run pnpm install in frontend/ (via a prepare script that points core.hooksPath at scripts/git-hooks). If you only ever run the stack through Docker and want it anyway, enable it manually once (worktrees of the same clone share it):
git config core.hooksPath scripts/git-hooksTo regenerate the client it needs the backend's Python deps. It finds them, in order: a host backend/python/venv, then a running f4k_backend container (Docker-only devs need the backend up — docker compose up backend), then a system python3 that can import the deps. If none are available it warns and skips rather than blocking the commit — on pull requests, CI regenerates the client (openapi.json and the generated TS) and commits the fix back to your branch automatically (via the f4k-openapi-sync GitHub App), so drift can't merge even if the hook never ran. You can also force-skip the hook with SKIP_OPENAPI_REGEN=1 git commit ….
See frontend/README.md for details.
docker-compose up --build| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Backend | http://localhost:8080 |
| API docs | http://localhost:8080/docs (dev only) |
# Check migration status
docker-compose exec backend alembic current
# Generate migration after model changes
docker-compose exec backend alembic revision --autogenerate -m "description"
# Apply migrations
docker-compose exec backend alembic upgrade head
# Connect to DB
docker-compose exec db psql -U postgres -d f4k
# Seed with test data
docker-compose exec backend python -m app.seed_databaseUse the interactive Swagger UI at http://localhost:8080/docs, or see the Postman Setup Guide.
The frontend consumes the API through a TypeScript client generated from FastAPI's OpenAPI schema. After making backend route or schema changes, regenerate with pnpm generate:api from frontend/. See frontend/README.md for details.
The emails are written as React Email components in frontend/emails/*.tsx — that is the only place to edit them. The HTML under frontend/emails/html/ and backend/python/app/templates/ is generated output; hand-editing either copy gets overwritten by the next export.
Placeholders are rendered as literal {{ Name }} text by the sources, so Jinja2 substitutes them at send time. The name of every placeholder is declared in backend/python/app/constants/email_config.py as that email's required_context, and backend/python/tests/test_email_template_placeholders.py fails if the two ever disagree.
After changing a template, regenerate both copies with one command from the repo root:
./scripts/sync-email-templates.shCommit both directories together; CI fails if they drift. To preview while editing, run pnpm run email:dev from frontend/.
docker-compose up --build # Start with fresh build
docker-compose up -d --build # Start in background
docker-compose down # Stop
docker-compose down --volumes # Stop and remove volumes
docker system prune -a --volumes # Clean up unused resources
docker compose down && docker volume rm food4kids_frontend_node_modules; docker compose build --no-cache frontend && docker compose up -d #regenerate pnpm- Frontend README — project structure, design system, TypeScript conventions
- Backend README — architecture, adding features, scheduled jobs, developer scripts
- CONTRIBUTING.md — version control, linting, testing, CI/CD, VSCode setup
Database connection errors
- Ensure Docker Desktop is running
- Check container health:
docker-compose ps - Verify
.envvalues - Try:
docker-compose down --volumes && docker-compose up --build
"ENOSPC: no space left on device" when building containers
docker system prune -a --volumes
docker-compose up --buildMigration errors
- Check status:
docker-compose exec backend alembic current - Ensure the database is running
- Verify model changes in
app/models/
Firebase authentication issues
- Verify Firebase config in your env files
- Ensure Firebase Admin SDK credentials are properly formatted