# FinData OS — web console Private operator console for the FinData OS lakehouse. Next.js 15 (App Router) + TypeScript + Tailwind CSS v4, built as a **static export** and served by the Python API — no Node process in production. ## Develop ```bash cd apps/web pnpm install pnpm dev # http://localhost:3000 — /api/* is proxied to http://127.0.0.1:8600 (next.config.ts rewrites, dev only) pnpm typecheck # tsc --noEmit ``` Start the API locally (`uv run uvicorn findata_api.main:app --port 8600`) before using the dev server; the console authenticates with the API's cookie session and sends `X-CSRF-Token` on every non-GET request. ## Build & serve ```bash pnpm build # → apps/web/out/ (index.html + one directory per route, trailing slashes) ``` `services/api/src/findata_api/main.py` mounts `apps/web/out` (or `FINDATA_WEB_DIST`) with `StaticFiles(html=True)`, so `/datasets/` serves `out/datasets/index.html`, and the console is same-origin with `/api/v1`. The CSP is `default-src 'self'` (inline styles allowed, inline scripts not); the bundle contains no inline scripts, external fonts or CDNs. ### CSP and the post-build step Next's App Router emits its React Server Components payload as inline `` tags, which `script-src 'self'` blocks. `pnpm build` therefore runs `scripts/externalize-inline-scripts.mjs` after `next build`: it moves those pushes, per page, into `out/_next/static/flight/.js` and replaces them with one blocking `