All posts
Team ZEUSDOGFOOD 2026 buildersdocker-composefastapinextjspostgrespgvectorsetup

The one command

The main branch boots three containers with a single command: PostgreSQL 16 with pgvector on :5432, the FastAPI backend on :8000, and the Next.js 14 frontend on :3000. No local Python or Node toolchains required — uv, npm, Node 20 and Python 3.11 all run inside the containers.

Clone, pin to main, and boot. First boot builds both app images, so give it a few minutes; later boots are fast.

git clone https://github.com/SVMoniss/Zeus-dogfoodhack.git dogfoodhack
cd dogfoodhack
git checkout main
docker compose up

What compose starts

postgres uses pgvector/pgvector:pg16 with db/user/password dogfood/dogfood, mounts init.sql (enables the vector and uuid-ossp extensions), and gates the other services on a pg_isready healthcheck.

backend builds src/backend/Dockerfile (python:3.11-slim), mounts ./src/backend for live reload, and runs seed.py, then alembic upgrade head, then uvicorn. frontend builds src/frontend/Dockerfile (node:20-alpine) and runs next dev with WATCHPACK_POLLING=true, which is required on Windows bind mounts or Next serves stale pages.

Seed data and test accounts

Boot auto-loads fixtures.json: 1 event (Sample Hack 2026, submissions already closed on purpose), 8 tracks, 30 judges, 40 teams and roughly 40 projects with ~200 scores.

Four fixed checker users are created with tokens that match .dogfood.toml: organizer, judge_a, judge_b and participant (password testpass123 for manual login). Keep the default SECRET_KEY until after you run the checker — the committed cookies are HMAC-signed with it.

docker compose down -v   # wipes postgres_data for a clean reseed
docker compose up --build

Verify: the 7/7 checker

run.py is stdlib-only — nothing to install. It checks the T1 gallery (public, fixture project shown, closed event refuses submissions) and the T2 judging guarantees (judge sees own scores, cannot see peer scores, participant blocked, CSV export works).

Health endpoints double as smoke tests: /health is static, /health/ready opens a real DB connection, so a ready response means postgres, migrations and networking are all good.

python3 run.py .dogfood.toml > acceptance-report.txt
curl http://localhost:8000/health/ready
curl http://localhost:8000/docs  # interactive OpenAPI

When it breaks

Five fixes cover nearly every setup failure: free ports 5432/8000/3000; run the checker before rotating SECRET_KEY; keep WATCHPACK_POLLING on Windows; use the compose postgres image so the vector extension exists; and keep backend FRONTEND_URL exactly matching the URL you open the frontend on, or CORS and auth cookies break.

Full-length version of this guide with the service-by-service env table lives in the repo at blog/setup-project-from-main.md.

Run it yourself

Every post maps to a real route or file in this repo. Start with the gallery, then the docs.

Browse projectsMore posts

Keep reading

View all