nornir-viz → wasm website — design
Class:
design· Function axis:f0the wasm slice (why a separate crate) ·f1the six wasm-capable facets (vs native-only) ·f2the eframe glow/WebGL app + headless contract ·f3theserveaxum host. Strict: only what is built. Sibling:build-design.md(the 🔨 Build tab, which is native-only — seef1). Source crate:nornir-viz-web.
f0 — the wasm slice (crates/nornir-viz-web)
Rickard's ask — "prepare a wasm for nornir viz … website with nornir … nornir viz → server nornir" — is answered by a viz-only crate, not by cross-compiling the whole nornir binary. The nornir crate is a native kitchen sink (redb warehouse, tonic gRPC, tokio, gix, candle/ort, rmcp) that cannot reach wasm32-unknown-unknown. The genuinely portable content of the viz is its facett Facets — pure egui components with CPU painters and no I/O — so nornir-viz-web depends on exactly those and builds them for the browser (lib.rs:1 module doc). The native viz (nornir viz → nornir-ui) is untouched and stays fully working.
f1 — the six wasm-capable facets (and what stays native-only)
WASM_CAPABLE (crates/nornir-viz-web/src/lib.rs:47) is the discoverable legend — the six components nornir's native viz embeds that cross to the browser, each a pure egui + CPU painter with no I/O:
| id | facet | crate |
jobview |
🧬 hierarchical / streaming job tree | facett-jobview |
metro |
🚇 subway-line view of test-coverage chains | facett-graphview::MetroView |
graph3d |
🌐 3-D node cloud (CPU-painted, orbit/spin) | facett-graph3d |
helix |
🧬 TIME-HELIX plan/dep DAG winding along release time | facett-helix |
warehousedeck |
🏢 multi-pane lakehouse deck (CPU graph3d panes) | facett-warehousedeck |
docview |
📖 vector-SVG documentation viewer (pure-Rust resvg) | facett-docview |
Native-only (the honest gate — NOT in this deck) because each needs a device / filesystem / threads the browser lacks: the 🔨 Build tab (spawns a real cargo build on a worker thread), the warehouse (redb), the gRPC / remote panes (tonic), file dialogs, and the wgpu GPU fast-paths (in wasm the CPU painters draw instead). This split is spelled out verbatim in the crate's module doc (lib.rs:21) so "what crosses" is documented, not guessed.
The deck is seeded with realistic demo data by nornir_viz_deck() -> FacetDeck (lib.rs:58) — no window, no I/O, so the headless self-check can construct it.
f2 — the eframe app + headless contract
NornirVizApp (lib.rs:124) is the eframe app: a facett_core::FacetDeck of the wasm-capable Facets that draws its own tab bar + the active facet. It runs through eframe on glow / WebGL (Cargo.toml wasm target: eframe with default-features = false, features = ["glow"] + wasm-bindgen + console_error_panic_hook) — no winit-native platform backend, no wgpu.
The same headless state_json contract the native viz exposes is exposed here: NornirVizApp::state_json (lib.rs:145) composes every facet's state_json plus the wasm_capable id list, and on wasm main.rs installs it as the window.__nornir_viz_state() JS hook so a browser drive can read what actually rendered.
f3 — the serve host ("nornir viz → server nornir")
nornir-viz-web the binary (crates/nornir-viz-web/src/main.rs) has two faces:
- native, no args — open the viz in a native eframe window (dev loop).
nornir-viz-web serve --dir <dist> [--addr 127.0.0.1:8080]— the "server nornir" path: an axum static host (main.rsmod serve,runatmain.rs:66, featureserve) that serves the built wasm bundle as a website viatower-httpServeDir, with anindex.htmlfallback so any route re-serves the SPA (main.rs:98), until Ctrl-C.
The serve feature is off by default (Cargo.toml [features]) so a plain cargo build and the wasm build pull no server stack. The wasm bundle itself is produced by ./build-wasm.sh (wasm-bindgen) into dist/, then handed to serve.