Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-demo/README.md

facett-demo — the live web demo + the reusable demo harness

facett-demo is the showcase: one eframe binary that exercises every facett component with fake-but-realistic data, switchable across all palettes. It builds two ways from the same panel code — a native desktop window and a wasm32-unknown-unknown bundle served on Codeberg Pages:

This document also specifies the reusable demo harness (facett-wasm-demo) that nornir, holger, and dwarves copy to stand up their own Pages demo with minimal glue.

Build & deploy

All automation is Rust in xtask/ — there is no YAML CI. From the workspace root:

command effect
cargo xtask demo-wasm build the release wasm bundle into dist/ (index.html + facett-demo.js + facett-demo_bg.wasm), a self-contained static site
cargo xtask deploy-pages run demo-wasm, then publish dist/ to the pages branch (force-pushed, single squashed commit) which Codeberg serves at the URL above

The build path is wasm-bindgen --target web (not trunk / wasm-pack). xtask self-bootstraps the wasm32-unknown-unknown target and a wasm-bindgen CLI whose version matches Cargo.lock (a mismatch is the classic blank-canvas failure). dist/ is git-ignored on main; it lives only on the pages branch.

The wasm build is --no-default-features: it drops the native-only region-clip (osm-katana) and the wgpu paint-callbacks, and runs the glow / WebGL backend with the CPU painters. Verify both hosts before deploying:

cargo build -p facett-demo                                              # native
cargo build --release -p facett-demo --target wasm32-unknown-unknown --no-default-features   # wasm

The state hook (verify the shipped bundle without a human)

The wasm bundle republishes its whole state_json — every tab, control, and the runtrace "what RAN" ledger — into a process global each frame, exported to JS as window.__facett_state(). A headless Chromium drive (or the browser console) reads it to confirm what actually rendered and ran in the shipped artifact. index.html lifts the named export onto window because --target web exports are module members, not globals. The document is served no-cache and the JS/wasm URLs carry a per-commit ?v=<sha> so a redeploy never serves a stale bundle.

The reusable harness — facett-wasm-demo

facett-wasm-demo is the "one panel, N hosts" edge, packaged so another repo gets a demo without re-deriving the eframe boot. It mounts a panel — a facett_core::Facet (title / ui / state_json) — onto:

The panel's fixture is whatever the consumer builds the Facet from; the harness never touches a backend, so it runs with no network and no filesystem (browser-safe). gRPC and direct-Rust calls stay first-class alongside this UI edge — the harness is only the canvas host.

facett-wasm-demo/examples/panel.rs is the copy-paste template. It builds native and wasm from the same source and exports its state hook.

How another repo (nornir / holger / dwarves) reuses it

  1. Depend on the harness in the repo's <repo>-demo crate:
[dependencies]
facett-wasm-demo = "0.1"   # path dep while co-developed; crate version once published
facett-core = "0.1"
egui = "0.34"
serde_json = "1"

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2"
  1. Copy examples/panel.rs into the crate's src/main.rs and swap HelloPanel for the repo's panel, built from its fixture (a holger registry-browser panel, a nornir timeline/dep-graph panel, a dwarves CI/CD facett-cicd panel). Rename the __demo_state export to __<repo>_state.

  2. Generate index.html in the repo's xtask after wasm-bindgen, from the one template — no per-repo HTML drift:

facett_wasm_demo::IndexHtml {
    stem: "holger-demo",          // wasm-bindgen emits <stem>.js + <stem>_bg.wasm
    canvas_id: "demo_canvas",     // must match WebDemo::new(...)
    title: "holger — live web demo",
    description: "the holger registry browser, in your browser",
    state_export: "__holger_state",
    cache_bust: &short_git_sha,
}
.write(&dist_dir)?;
  1. Deploy to the repo's pages branch (Codeberg serves it at https://nordisk.codeberg.page/<repo>/). facett's xtask deploy-pages is the reference: build wasm → wasm-bindgen --target web → write index.html + .nojekyll + .domains → force-push dist/ to pages.

Where a repo's panel is not yet a wasm component (the WIT panel world in dwarves/.nornir/ui-embedding-and-standalone.md), the demo ships facett's own render of the panel as a labelled interim, and upgrades to the true component artifact when that seam lands. The harness API is unchanged either way — it mounts whatever Facet / eframe::App it is handed.