# Nat20 Notes — agent guide ## Commands - `make deps` — one-time build of the heavy WhisperX/PyTorch layer (5-10 min) - `make build` — fast app-only rebuild (seconds) - `docker compose pull && docker compose up -d` — pull & run pre-built images from registry - `cd frontend && npm run dev` — Vite dev server (proxies `/api` → `localhost:8000`) - **No tests, no lint/typecheck scripts exist.** Don't look for them. ## Architecture - Two Docker Compose services: `backend` (Python 3.11, FastAPI, SQLite, WhisperX as lib) and `frontend` (React 18 + Vite + Tailwind, served by nginx which proxies `/api` → backend). - Data lives in Docker volume `app_data` at `/data` (SQLite DB + `uploads/audio/transcripts/notes` subdirs). No external DB. - Background jobs (transcribe, summarize) run via in-process `ThreadPoolExecutor(max_workers=2)` — no Redis/Celery. - Frontend serves on port **8020** (d20 nod). ## Critical convention: per-campaign settings schema Settings are split into **global** (`settings` table, just `onboarding_completed`) and **per-campaign** (`campaign_settings` table, everything else). Every layer must share the exact same keys: `backend/app/config.py:CAMPAIGN_SETTINGS`, `frontend/src/api.ts:CampaignSettings`, campaigns router, and Settings/Setup pages. New campaigns inherit settings from the "default" campaign on creation. The settings router (`/api/settings`) only handles global; campaign settings live at `/api/campaigns/{id}/settings`. When adding a setting key, add it to `config.py:CAMPAIGN_SETTINGS`, the frontend type, and both the backend router and frontend Settings page. ## Docker / framework quirks - Torch pinned to `2.3.1` with `cu121` wheels (`--extra-index-url https://download.pytorch.org/whl/cu121`) — cuDNN ABI compat with `ctranslate2`. Don't bump unpinned. - Backend has two Dockerfiles: - `Dockerfile` — thin, app-only. Starts `FROM nat20-whisperx-base:latest`. Used by CI for fast rebuilds and by `make build`. - `Dockerfile.deps` — full WhisperX base layer. Build once per `requirements.txt` change. Used by CI and `make deps`. - `Makefile` — `make deps` builds the heavy layer; `make build` does fast app-only rebuild. - **CI/CD pattern**: Gitea runner builds & pushes `nat20-whisperx-base:latest` only when `requirements.txt` changes, then builds & pushes `backend:latest` (thin) on every push. Your `docker compose pull` only downloads new app layers (~100 KB) — the 3 GB WhisperX layer stays cached. - ffmpeg required in runtime for audio extraction. - nginx `client_max_body_size` 500M, proxy timeouts 3600s. Files >15MB auto-chunked by frontend `createSession()`. - Frontend changes in Compose mode require a rebuild (`docker compose up -d --build`). Vite dev server is for local-only dev. ### Optimised rebuild workflow ```bash # One-time: build the heavy WhisperX/PyTorch layer make deps # Daily: rebuild only app code (seconds, not minutes) make build # Or with docker compose if you've done make deps first: docker compose up -d --build ``` ## Auth - First user is admin, created from `NAT20_ADMIN_USERNAME` / `NAT20_ADMIN_PASSWORD` env vars on first startup. - Admin can create users via the Users page. Users can share campaigns with other registered users. - JWT tokens (HMAC‑SHA256, 7-day expiry) stored in localStorage. Global fetch interceptor adds `Authorization: Bearer` to all `/api/` calls. ## Tailwind theme Custom colors (`deep`, `panel`, `brass`, `ember`, etc.) and fonts (`Fraunces`, `Inter`, `IBM Plex Mono`) in `tailwind.config.js`. Reusable component classes in `frontend/src/styles.css` (`.card`, `.btn-primary`, `.btn-secondary`, `.input`, `.eyebrow`) — use these over raw Tailwind utilities. ## Constraints - Requires NVIDIA Container Toolkit + HuggingFace token for speaker diarization. - First run: setup wizard, then `onboarding_completed` flag gates access to main UI. - Default Ollama endpoint: `http://localhost:11434`.