The web command center for Astra — upload a neural network, watch the sensitivity-guided Pareto search run, explore the 3D architecture/Pareto views, and monitor live telemetry. A React + Vite single-page app with a Linear/Raycast dark aesthetic.
Deep design & engineering guide lives in
CLAUDE.md— the authoritative doc for IA, design tokens, conventions, and per-screen specs. This README is the quick start.
| Area | Choice |
|---|---|
| Build | Vite 5 (ESM, fast HMR) |
| Language | TypeScript 5 (strict: noUncheckedIndexedAccess, noUnusedLocals/Parameters) |
| UI | React 18 + Tailwind CSS 3 + Radix UI (headless) |
| Server state | TanStack Query v5 · UI state Zustand · URL state React Router v6 |
| 3D | three.js + @react-three/fiber + @react-three/drei |
| Charts | Recharts |
| Motion / forms | framer-motion · react-hook-form + zod |
| Code highlight | shiki |
| Tooling | ESLint + Prettier · Playwright (e2e) |
Package manager: pnpm 9.15.4 (pinned via packageManager, activated by Corepack). Node 22 (.nvmrc).
corepack enable # activates the pinned pnpm
pnpm install --frozen-lockfile
pnpm dev # http://localhost:5173 — proxies /api → :8000The dev server proxies /api/* to the backend. Point it elsewhere with
VITE_API_TARGET (see Environment); copy .env.example →
.env.local to set it locally.
| Script | Purpose |
|---|---|
pnpm dev |
Vite dev server (HMR) |
pnpm build |
Type-check + production build → dist/ (tsc -b && vite build) |
pnpm preview |
Serve the built dist/ locally |
pnpm typecheck |
tsc -b --noEmit |
pnpm lint / pnpm lint:fix |
ESLint (TS + React + import-sort + tailwind) |
pnpm format / pnpm format:check |
Prettier write / check |
pnpm test / pnpm test:e2e |
Playwright e2e (alias) |
pnpm test:e2e:ui |
Playwright inspector |
The only build-relevant variable is VITE_API_TARGET (read in
vite.config.ts), and it is dev-only: it sets where the Vite dev server
proxies /api/*.
- Default:
http://localhost:8000(standalone FastAPI). - Set to
http://localhost:8080to route through the Caddy single-origin stack.
In production there is no build-time env: Caddy serves the SPA and proxies
/api from one origin, so the session cookie works without any cross-origin
setup. See .env.example.
src/
├─ app/ # entry, router, providers (QueryClient, Theme, Toast)
├─ pages/ # one thin component per route
├─ features/ # domain modules: dashboard, models, architecture,
│ # pareto, telemetry, sdk-hub, auth, docs
├─ components/ # shared: ui/, layout/, charts/, three/, feedback/,
│ # marketing/, command/, icons/
├─ hooks/ stores/ lib/ i18n/ api/ styles/ assets/
Routing is createBrowserRouter with lazy pages; /models/:modelId is a 4-tab
shell (Architecture · Pareto · Telemetry · SDK Hub). The API client
(src/api/client.ts) calls relative /api/* with credentials: "include"
(cookie auth) — never absolute URLs. Full conventions in CLAUDE.md.
Playwright e2e drives the app with a mocked API (per-test page.route
interception), so no backend is required. The suite auto-starts the dev
server.
pnpm exec playwright install chromium # once, on a fresh machine
pnpm test:e2e # all specs (desktop + mobile)
pnpm exec playwright test app.spec.ts --project=desktop # quick functional subsetThere are no unit tests yet; lib/ and hooks/ are the natural first targets
(Vitest) when adding them.
pnpm build # → dist/ (source maps off; ~9MB)
pnpm preview # smoke-test the buildProduction is containerized: a multi-stage Dockerfile builds the SPA on
node:22-slim and serves the static dist/ from caddy:2-alpine, which also
reverse-proxies /api to the backend (BACKEND_UPSTREAM).
The frontend deploys independently of the backend via
deploy/docker-compose.yml:
cd deploy
cp .env.example .env # set BACKEND_UPSTREAM (+ TUNNEL_TOKEN for the tunnel)
docker compose --profile tunnel up -d --buildLive topology (https://astra.kwon5700.kr): the frontend runs in a Proxmox
LXC behind a Cloudflare Tunnel (TLS at the edge → Caddy :80); the
backend (API · worker · Postgres · Redis · MinIO) runs via docker-compose in a
separate Proxmox VM, reached over the private network
(BACKEND_UPSTREAM=http://<VM-IP>:8000). The full procedure — Cloudflare Tunnel
setup, the backend env checklist (ASTRA_PUBLIC_ORIGIN, ASTRA_COOKIE_SECURE,
…), and SSE notes — is in deploy/README.md.
.github/workflows/ci.yml runs typecheck → lint → build on every push/PR, with
Playwright e2e in a separate lane.