A web app for displaying and interacting with simulation videos spread across a parameter hypercube.
For the full local experience:
npm install
npm run localOpen http://localhost:5173.
For cloud-only browsing without local assets or local tracking:
npm install
npm run devOpen http://localhost:5173 — the app streams assets from the cloud by default.
For a full offline setup, asset downloads, local tracking, and production workflows, see Running Locally.
- Node.js >= 18 (Vite 6 requires ESM support; Node 18 is the minimum supported LTS)
- Python >= 3.9 for asset-generation scripts
- ffprobe (part of
ffmpeg) forscripts/generate_run_summaries.py
| Command | What it does |
|---|---|
npm install |
Install dependencies |
npm run local |
One-command local launcher |
npm run dev |
Start dev server |
npm run dev:local |
Start dev server forced to local manifest mode |
npm run setup:local |
Download assets and generate local manifest |
npm run generate:run-manifest |
Regenerate public/assets/local-manifest.json |
npm run build |
Production build |
npm run format |
Format source files |
npm run format:check |
Check formatting (CI) |
python3 scripts/generate_run_summaries.py |
Refresh per-run run_summary.yaml files |
npm run download:assets |
Download all cloud assets to public/assets/ |
npm run download:cosmos |
Download cosmos cloud assets only |
npm run tracking:server |
Start local tracking server |
npm run tracking:sync |
Sync local tracking DB to online D1 |
The app now has a password-gated Advanced Settings section inside the normal Settings overlay.
Advanced settings include:
- locking the app to a single cosmic scale
- choosing manifest source:
localoronline - toggling verbose console logging
- hiding selected scales from the landing screen
Current default behavior:
- the app defaults to
onlinemanifest mode - online manifest mode fetches the bucket-hosted
run-manifest.jsonfrom the fixed URL insrc/shared/constants.ts localmanifest mode is still available in Advanced Settings as an explicit fallback overridenpm run dev:localforces local manifest mode regardless of previously saved browser settings
The app currently uses a four-mode interface:
entry- first-load simulation-family chooserconfig- overlay for parameter tuning and theme settingsinitializing- terminal-style faux startup window shown after rundisplay- viewport with telemetry panel, timeline, and a burger menu that opensHome,Settings,Credits, andFullscreen
Inside Settings, the Advanced Settings section is password-gated for exhibit / kiosk style controls.
See UI_ARCHITECTURE.md for the current component and state breakdown.
src/main.ts- browser entrypoint (imports global CSS, boots the app)src/app/- app shell/orchestrationsrc/entry/- landing screen / scale selection overlaysrc/loading/- initialization overlay and boot textsrc/live-data/- CSV parsing, HUD sampling, telemetry presentationsrc/selection/- parameter editor, settings overlay, theme picker, manifest-backed asset lookupsrc/shared/- cross-cutting helpers like URLs, logging, and advanced settings persistencesrc/summaries/- run summary overlay and metricssrc/video_player/- viewport, view switcher, and timelinescripts/- manifest, summary, and upload utilitiespublic/assets/- local runtime assets and generated manifests
Simulation assets live under public/assets/ using a run-based layout:
public/assets/<simulation-id>/<run-id>/animations/*.mp4public/assets/<simulation-id>/<run-id>/live_data_table.csvpublic/assets/<simulation-id>/<run-id>/final_snapshot_summary.csvpublic/assets/<simulation-id>/<run-id>/run_summary.yaml
The frontend resolves the nearest available run through a generated manifest.
Current manifest files:
public/assets/local-manifest.json- default local manifest used by the apppublic/assets/run-manifest.json- optional online manifest intended for Cloudflare-hosted assets
Run this when final_snapshot_summary.csv, live_data_table.csv, or the videos have changed:
python3 scripts/generate_run_summaries.pyThis writes one run_summary.yaml file per run directory.
Note: this script requires ffprobe to be available on your machine.
This is the default manifest used by the app today:
npm run generate:run-manifestEquivalent explicit form:
python3 scripts/generate_run_manifest.py --local --output "public/assets/local-manifest.json"This writes:
public/assets/local-manifest.json
To prepare local assets if needed, start local tracking, and launch the app in local-manifest mode with one command:
npm run localLower-level helpers remain available when you want more control:
npm run setup:local
npm run dev:local
npm run tracking:serverThe online manifest is generated from the actual R2 bucket contents under the
fixed engine/ prefix.
Set these environment variables first:
export R2_BUCKET="YOUR_BUCKET"
export R2_PUBLIC_BASE="https://YOUR_PUBLIC_R2_BASE"
export R2_BACKUP_BASE="https://YOUR_BACKUP_R2_BASE"
export R2_ACCOUNT_ID="YOUR_ACCOUNT_ID"
export R2_ACCESS_KEY_ID="YOUR_ACCESS_KEY_ID"
export R2_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY"Then generate the online manifest:
python3 scripts/generate_run_manifest.pyThis writes:
public/assets/run-manifest.json
The generator:
- scans the actual bucket contents below
engine/ - groups objects into simulation runs
- fetches
parameters.yamlwhen present - writes the frontend manifest based on what is actually online
If you have changed local assets, run:
python3 scripts/generate_run_summaries.py
npm run generate:run-manifestIf you are preparing a Cloudflare-backed manifest, run:
python3 scripts/generate_run_summaries.py
python3 scripts/generate_run_manifest.pyManifest generation is intentionally separate from the upload step.
- Generate
public/assets/run-manifest.jsonlocally. - Upload the assets tree to R2.
- Upload the already-generated manifest as a final publishing step.
Example:
python3 scripts/generate_run_manifest.py
python3 scripts/upload_engine_assets_to_r2.py --assets-dir public/assets --manifest-path public/assets/run-manifest.jsonOr, if you only need to publish the manifest after regenerating it:
python3 scripts/upload_run_manifest_to_r2.pyThe manifest generator:
- scans
public/assets/planetary/,public/assets/galaxy/, andpublic/assets/cosmos/ - reads
parameters.yamlwhen present - falls back to supported parameter tokens in the run directory name when needed
- writes either a local or online manifest depending on flags
Current supported cosmos run-name tokens are:
Fb->baryon_fractionEf->black_hole_strengthG->gravity_strength
The manifest keeps local relative asset paths today, but the same schema can later be regenerated as run-manifest.json with remote URLs for Cloudflare-hosted assets.
A standalone test page for the end-of-run summary overlay lives at
tests/summary-test.html. It renders the summary screen exactly as the
app does — same CSS, same layout, same data pipeline — without requiring
a full video playback session.
- Dropdown to switch between simulation families (Planetary, Galaxy, Cosmos)
- Visual theme picker (Glass, Matrix, HAL 9000, Nostromo, Tron)
- Paired range slider + number input for every parameter in the selected family
- Configurable video duration (affects runtime formatting)
- Placeholder final-frame image (the hero panel is intentionally not the numeric score gauge — that path only triggers when no thumbnail is available, which never happens in the app)
npm run devThen open http://localhost:5173/tests/summary-test.html.
The control panel floats top-right so you can tweak parameters and re-show the overlay without reloading.
- Visually verifying summary layout, card grids, result bars, and modal detail pop-ups across all simulation families and visual themes
- Catching regressions when YAML configs (parameter ranges, stat config, target messages) are updated
- Checking that per-family scoring behaviour (bar score vs. similarity fallback) produces the expected hero verdict and colour
- If
Advanced Settingsis set toonlinebefore the online manifest exists, the app will fall back gracefully to placeholder assets. - Verbose logging can be enabled in
Advanced Settingsfor parameter-selection and manifest/debug output.