Spaces:
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:
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.
cd webapp/frontend
npm install
npm run dev
npm run build
npm run lint
Run both servers together from the repository root:
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:
make pareto-fronts
Pass extra arguments through SCRIPT_ARGS:
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 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
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)
# 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:devboots cleanly;curl localhost:8000/healthzreturns{"status":"ok","surrogate_loaded":true,...}. - Set
ROVERDEVKIT_CORS_ORIGINSto the platform's hosted origin (e.g.https://huggingface.co,https://<user>-<space>.hf.space). Defaults tohttp://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 viaROVERDEVKIT_QUANTILE_BUNDLES); seewebapp/backend/config.pyfor the full env-var surface. - (HF Spaces) drop a
Dockerfilesymlink or a one-lineSpaces config: dockerblock at the repo root that points atwebapp/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
pytest webapp/backend/tests -q
cd webapp/frontend && npm run lint && npm run build
The top-level helper runs the same checks:
make webapp-test