Spaces:
Running
Running
| # RoverDevKit Web App | |
| The web app provides an interactive interface for RoverDevKit's mission | |
| evaluator, surrogate predictions, parametric sweeps, multi-objective design | |
| optimization, and SHAP-style design explanations. | |
| ``` | |
| webapp/ | |
| ├── backend/ FastAPI app over the roverdevkit Python package | |
| └── frontend/ React + Vite + TypeScript single-page app | |
| ``` | |
| ## Backend | |
| The backend is a thin FastAPI layer over the Python evaluator and trained | |
| surrogate artifacts. The API keeps the browser UI aligned with the same models | |
| used by scripts and notebooks. | |
| Common routes: | |
| | Method | Path | Purpose | | |
| | --- | --- | --- | | |
| | GET | `/healthz` | Liveness and artifact-presence probe. | | |
| | GET | `/version` | Dataset, surrogate, and git version metadata. | | |
| | GET | `/scenarios` | List bundled mission scenarios. | | |
| | GET | `/scenarios/{name}` | Return one scenario and its nominal soil parameters. | | |
| | GET | `/registry` | Return published rover registry entries. | | |
| | POST | `/predict` | Surrogate median and 90% interval for one design. | | |
| | POST | `/evaluate` | Physics evaluator output for one design. | | |
| | POST | `/sweep` | One- or two-dimensional parametric sweep. | | |
| | POST | `/optimize` | Start an NSGA-II multi-objective optimization job. | | |
| | GET | `/optimize/{job_id}/stream` | Stream optimization progress with server-sent events. | | |
| | GET | `/optimize/{job_id}/result` | Fetch a completed optimization result. | | |
| | POST | `/shap/explain` | Explain one current design prediction. | | |
| ## Run Locally | |
| From the repository root, with the `roverdevkit` conda environment activated: | |
| ```bash | |
| conda activate roverdevkit | |
| pip install -e ".[webapp]" | |
| uvicorn webapp.backend.main:app --reload --port 8000 | |
| ``` | |
| OpenAPI docs are available at <http://localhost:8000/docs>. | |
| ## Frontend | |
| The frontend is a Vite + React + TypeScript app. Its typed fetch client lives in | |
| `src/lib/api.ts`, and the dev server proxies backend routes to | |
| `http://localhost:8000`. | |
| ```bash | |
| cd webapp/frontend | |
| npm install | |
| npm run dev | |
| npm run build | |
| npm run lint | |
| ``` | |
| Run both servers together from the repository root: | |
| ```bash | |
| make webapp-dev | |
| ``` | |
| Open <http://localhost:5173> after the frontend server starts. | |
| ## UI Sections | |
| - **Current Design** evaluates the active rover design under the mission inputs | |
| (scenario, scientific-payload mass and power, operational duty cycle). Payload | |
| is a mission requirement set at the top of the panel, not a design variable. | |
| - **Parametric Sweep** explores one- and two-variable design sensitivities. | |
| - **Optimize Design** runs NSGA-II searches and visualizes completed Pareto | |
| fronts. | |
| - **Explain Design** shows SHAP-style feature attributions for the active | |
| design and selected target. | |
| ## Canonical Pareto Fronts | |
| The Optimize Design tab always runs NSGA-II live against the corrected | |
| physics evaluator. There is no in-app "load reference" affordance because | |
| the live job completes in ~30–60 seconds at the default budget and produces | |
| evaluator-truth points anyway. | |
| The repo still ships a precomputed reference set under | |
| `reports/pareto_fronts/` (one CSV + metadata JSON per canonical scenario, | |
| plus a top-level `manifest.json`). These are reference artifacts for | |
| documentation figures and notebook fixtures; the evaluator is | |
| deterministic and each file is small (~14 kB), so they are committed | |
| to the repo for reproducibility. | |
| Regenerate them whenever scenario configs change: | |
| ```bash | |
| make pareto-fronts | |
| ``` | |
| Pass extra arguments through `SCRIPT_ARGS`: | |
| ```bash | |
| make pareto-fronts SCRIPT_ARGS="--population-size 80 --generations 80" | |
| ``` | |
| The default settings (50-point population, 60 generations, analytical | |
| Bekker-Wong evaluator) complete all four canonical scenarios in about | |
| 4 minutes on a laptop. | |
| ## Docker / Hosted Deploy | |
| A multi-stage [`webapp/Dockerfile`](Dockerfile) builds the React frontend | |
| with Node 20 LTS, then installs the Python package + the `[webapp]` | |
| extras on top of `python:3.12-slim` and bakes in: | |
| - the analytical Bekker-Wong mission evaluator, | |
| - the v9 quantile-XGB surrogate bundles | |
| (`models/surrogate_v9/quantile_bundles.joblib`), | |
| - the canonical Pareto fronts (`reports/pareto_fronts/`), | |
| - the built React frontend at `/app/static`. | |
| The runtime image runs a single `uvicorn` process that serves the | |
| FastAPI backend at `/healthz`, `/predict`, `/evaluate`, `/sweep`, | |
| `/optimize`, `/shap`, `/registry`, `/scenarios`, and serves the React SPA off | |
| `ROVERDEVKIT_STATIC_DIR=/app/static` with a history-mode catch-all so | |
| deep links survive a hard refresh. | |
| ### Local boot via Docker Compose | |
| ```bash | |
| docker compose -f webapp/docker-compose.yml up --build | |
| ``` | |
| Open <http://localhost:8000>. First boot takes 2-3 min for the | |
| `pip install` layer; subsequent rebuilds reuse the wheel cache and | |
| finish in ~30 s for a code-only edit. | |
| ### Direct `docker build` (e.g. for CI or a one-off image push) | |
| ```bash | |
| # Build context must be the repo root so the Dockerfile can reach | |
| # pyproject.toml, roverdevkit/, data/, models/, reports/, and webapp/. | |
| docker build -f webapp/Dockerfile -t roverdevkit/webapp:dev . | |
| docker run --rm -p 8000:8000 roverdevkit/webapp:dev | |
| ``` | |
| ### Hosted-demo readiness checklist | |
| The image is intentionally hosting-platform agnostic. To stand it up | |
| on Hugging Face Spaces, Fly.io, Railway, or a Duke container, walk | |
| through this checklist: | |
| - [ ] `docker build -f webapp/Dockerfile -t roverdevkit/webapp:dev .` | |
| succeeds locally; record the resulting image size (~700 MB | |
| compressed for the v9 surrogate bundle). | |
| - [ ] `docker run --rm -p 8000:8000 roverdevkit/webapp:dev` boots | |
| cleanly; `curl localhost:8000/healthz` returns | |
| `{"status":"ok","surrogate_loaded":true,...}`. | |
| - [ ] Set `ROVERDEVKIT_CORS_ORIGINS` to the platform's hosted origin | |
| (e.g. `https://huggingface.co,https://<user>-<space>.hf.space`). | |
| Defaults to `http://localhost:5173` (Vite dev server) which | |
| will block browser calls in prod. | |
| - [ ] If the platform fronts the container with TLS, leave the | |
| Dockerfile's `--proxy-headers --forwarded-allow-ips=*` flags | |
| in place so client IP / scheme propagate from the edge. | |
| - [ ] Confirm the image runs as `roverdevkit` (UID 1000) — Fly.io, | |
| HF Spaces, and most K8s pod-security policies require non-root. | |
| - [ ] If the deploy uses a persistent volume to mount alternate | |
| surrogate artefacts, point the volume at | |
| `/app/models/surrogate_v9/quantile_bundles.joblib` (or | |
| override via `ROVERDEVKIT_QUANTILE_BUNDLES`); see | |
| `webapp/backend/config.py` for the full env-var surface. | |
| - [ ] (HF Spaces) drop a `Dockerfile` symlink or a one-line | |
| `Spaces config: docker` block at the repo root that points at | |
| `webapp/Dockerfile`. | |
| ### Image size and build context | |
| `.dockerignore` at the repo root excludes the LHS training corpora | |
| (`data/analytical/`), the training-time reports, any superseded | |
| surrogate versions, and Node / Python build caches. Only the runtime | |
| artefacts the backend actually loads — the current surrogate bundle | |
| (`models/surrogate_v9/quantile_bundles.joblib`) and the Pareto fronts | |
| — are baked into the image. | |
| ## Tests | |
| ```bash | |
| pytest webapp/backend/tests -q | |
| cd webapp/frontend && npm run lint && npm run build | |
| ``` | |
| The top-level helper runs the same checks: | |
| ```bash | |
| make webapp-test | |
| ``` | |