# 0.1. Quick Start From a fresh clone to a running 3F stack in a few commands. Everything happens inside containers — the only host requirements are Docker and (optionally) Ollama for local inference. ## Prerequisites | Requirement | Purpose | | -------------------------------------------------------------- | -------------------------------------------------------- | | Docker + Docker Compose v2 (with BuildKit) | All services run containerised | | [Ollama](https://ollama.com/) (optional) | Local model inference; skip when using Ollama Cloud only | | An Ollama model with vision support (e.g. `qwen3-vl`, `llava`) | Image/chat intelligence, `ollama pull ` | | `SERPER_API_KEY` (optional) | Web/news/image/video search tools for the agent | | `BRIGHT_DATA_API_KEY` (optional) | Alternative search provider (SERP + Web Unlocker) | | `YOUTUBE_API_KEY` (optional) | YouTube Data API v3 video search for the agent | ## 1 — Environment files ```bash cp server/.env.example server/.env cp dashboard/.env.example dashboard/.env ``` The committed examples are ready for local development. See **0.2-docker** for the full contract and **1-server** for every variable. Important keys: | Variable | Default (local) | Notes | | ---------------- | ------------------------ | --------------------------------------------------------------- | | `OLLAMA_HOST` | `http://localhost:11434` | Set to `https://ollama.com` + `OLLAMA_API_KEY` for Ollama Cloud | | `SERPER_API_KEY` | — | Enables Serper tools (search, images, news, videos …) | | `BRIGHT_DATA_API_KEY` | — | Enables Bright Data tools (alternative to Serper; SERP + Web Unlocker) | | `YOUTUBE_API_KEY` | — | Enables the YouTube video search tool (Data API v3) | | `POSTGRES_URL` | local DSN | Overridden by `compose.yml` for in-network resolution | ## 2 — Start the infrastructure ```bash docker compose -f infra.compose.yml up -d ``` Brings up **PostgreSQL 16** (`5432`), **MinIO** (`9000`, console `9001`), **KeyDB** (`6379`, configured by `server/keydb.conf`), and a **`playwright-mcp`** headless-chromium sidecar (loopback-only on `8931`) that exposes `browser_*` automation tools to the harness (see **1.2**). Ollama and SearXNG services are included but commented out — enable them if you want containerised inference or a local search frontend. ## 3 — Start the application ```bash docker compose up -d ``` That's it. Compose builds one shared image (`triplef-local`) and starts three services: 1. **`deps`** (one-shot) — runs `pnpm install --frozen-lockfile` for the entire workspace from the repo root and exits. It is the _only_ component allowed to touch `node_modules`. 2. **`server`** — waits for `deps` to finish, then starts NestJS in watch mode at `http://localhost:3000` (API under `/api/v1`, Swagger at `/api-docs`). 3. **`dashboard`** — waits for `server`, then starts Vite at `http://localhost:5173/dashboard/`. Both app services bind-mount the repository and hot-reload on save. No restarts or rebuilds are needed for source changes under `server/` or `dashboard/`. ## 4 — Verify ```bash curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/v1/health/live # 200 curl -s -o /dev/null -w '%{http_code}\n' http://localhost:5173/dashboard/ # 200 docker compose ps # server/dashboard Up, deps Exited (0) ``` Open `http://localhost:5173/dashboard/`, pick a model, and start talking. ## Daily workflow | Task | Command | | ---------------------------------- | ------------------------------------------------------------------------------------ | | Start everything | `docker compose -f infra.compose.yml up -d && docker compose up -d` | | Follow server logs | `docker compose logs -f server` | | Stop the app (keep infra) | `docker compose down` | | Stop everything | `docker compose down && docker compose -f infra.compose.yml down` | | Re-install deps (lockfile changed) | `docker compose up deps && docker compose up -d --force-recreate` | | Run scripts inside containers | `docker compose exec server pnpm ` · `docker compose exec dashboard pnpm ` | ## Rules that keep the stack healthy 1. **Install only at the repo root** — `pnpm install`, `pnpm --filter server add `. Installing _inside_ `server/` or `dashboard/` against stale standalone state can flip `node_modules` back to a per-app layout (and per-app lockfiles). The `deps` service guarantees containers stay on the shared workspace layout — see **0.2-docker** for why. 2. **Never delete `node_modules`** as a troubleshooting step. That was a workaround for the old dual-lockfile regime; the current setup makes it unnecessary and harmful. 3. If state _did_ drift (e.g. after running standalone Dockerfiles), the deterministic reset is: `rm -rf server/node_modules dashboard/node_modules node_modules server/pnpm-lock.yaml dashboard/pnpm-lock.yaml && docker compose up -d --force-recreate`. ## Tests & quality gates ```bash pnpm -r test # Vitest in both workspaces pnpm -r lint # ESLint + Prettier (flat configs) pnpm -r depcruise # dependency-cruiser architecture rules pnpm -r lint:unused # ts-unused-exports ``` CI runs the same gates on every branch (`non-release.ci.yml`); `main` additionally versions with changesets and regenerates badges (`release.ci.yml`, see **0.3-documentation**).