Sahil Bhatti's portfolio site and a working demonstration of production AI backend infrastructure: RAG, LLM observability, admin operations, Substack ingestion, and deployable services.
Prerequisites: Node 20+, pnpm 9.12, Python 3.12, uv, Docker.
corepack enable
corepack prepare pnpm@9.12.0 --activate
pnpm install
uv sync --all-packages --all-extras
cp infra/.env.example .env
docker compose -f infra/docker-compose.yml up -d postgres redis
cd services/api && uv run --package engine-room-api alembic upgrade head && cd ../..
uv run python infra/seed.pyStart the apps in separate terminals:
uv run --package engine-room-api uvicorn app.main:app --app-dir services/api --reload --port 8000PYTHONPATH=services/worker:services/api uv run --package engine-room-worker python -m app.schedulerpnpm devLocal URLs:
- Public site:
http://localhost:3000 - Admin console:
http://localhost:3001 - API health:
http://localhost:8000/api/health - API docs:
http://localhost:8000/docs
- Frontend: Next.js App Router, TypeScript, Tailwind, Framer Motion
- Backend: FastAPI, Pydantic v2, SQLAlchemy 2.0, Alembic
- Data: PostgreSQL 16 + pgvector, Redis
- AI: OpenAI embeddings, Anthropic generation through an LLM gateway
- Auth: NextAuth email magic link for the admin app,
ADMIN_TOKENfor admin API calls - Observability: OpenTelemetry collector, console exporter in dev, configurable OTLP export in prod
- Deploy: Docker Compose production stack, Caddy auto-TLS, Fly.io configs, GitHub Actions
apps/web Public Next.js site
apps/admin Admin Next.js console
services/api FastAPI backend and Alembic migrations
services/worker APScheduler ingestion/maintenance worker
packages/ui Shared design tokens, motion, primitives
packages/types Generated TypeScript API types
infra Docker, Fly, OTel, seed, backup, env templates
docs/AGENTS.md Phase 2 parallel-agent contracts
pnpm lint
pnpm typecheck
pnpm build
uv run ruff check services infra/seed.py
cd services/api && uv run --package engine-room-api alembic check
uv run --package engine-room-api pytest services/api/testscp infra/.env.production.example infra/.env.production
# edit infra/.env.production: domains, secrets, provider keys, backup bucket
docker compose --env-file infra/.env.production -f infra/docker-compose.prod.yml up -d --buildCaddy is the only public container. It serves the public site at DOMAIN, the admin app at ADMIN_DOMAIN, and proxies /api/* to FastAPI.
fly apps create engine-room-api
fly apps create engine-room-web
fly apps create engine-room-admin
fly postgres create --name engine-room-db --region sjc --volume-size 10
fly postgres attach --app engine-room-api engine-room-db
fly secrets set --app engine-room-api ADMIN_TOKEN=... OPENAI_API_KEY=... ANTHROPIC_API_KEY=...
fly secrets set --app engine-room-admin AUTH_SECRET=... ADMIN_EMAIL=... ADMIN_TOKEN=... RESEND_API_KEY=... EMAIL_FROM=...
fly deploy --config infra/fly/api.fly.toml --remote-only
fly deploy --config infra/fly/web.fly.toml --remote-only
fly deploy --config infra/fly/admin.fly.toml --remote-onlyGitHub Actions deploys the three Fly apps on pushes to main when FLY_API_TOKEN is configured.
Seed data after migrations:
uv run python infra/seed.pyBack up Postgres to S3-compatible storage:
export BACKUP_DATABASE_URL=postgresql://engine_room:password@host:5432/engine_room
export S3_BUCKET=engine-room-backups
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
infra/backup.sh