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

nordisk/facett

.nornir/design.md

facett — design (f0: the whole architecture)

Class: design · Function axis: this is f0 — how every facett function wires into one system. Each function has its own -design.md (linked below); this file is the spine that draws them together. Strict: only the shape we run — every why is in reasoning.md.

What facett is

facett is reusable data-viewing components for egui — each component is a facet of your data. Source-agnostic: hand one an Arrow RecordBatch, a graph, geo, or a DAG and it draws it, fast. It holds no connection or query logic (that stays in the data layer, e.g. knut). korp and nornir both build on it.

The two-part spine every component shares

facett is not a pile of widgets — it is one contract, twice. Every component sits on two stacked contracts, and everything else is a component family plugged onto that spine:

  1. The host-facing contract — Facet. One trait: title / ui / state_json (+ a defaulted capability surface). A component is a Box<dyn Facet>; a FacetDeck composes many into one tabbed app and yields whole-app introspection for free. This is what makes "many components" compose.
  2. The internal contract — Elm. Inside a component, all observable state is one serializable Model, mutated only in update(&mut self, Msg), painted by a pure view(&self) -> Vec<Msg>. The macro impl_facet_via_elm! writes the Facet impl from the Elm impl. This is what makes any component testable without a window.

Between them they give the whole library its two defining properties: compose (Facet + FacetDeck) and assert headless (Elm + harness). 36 components impl Elm today.

The reuse graph (what uses what)

                 ┌──────────────── egui 0.34 ────────────────┐
   facett-core   │  Facet · FacetDeck · FacetCaps · clipboard │  ← f: facet
   (the kernel)  │  Elm · impl_facet_via_elm! · harness       │  ← f: elm, harness
                 │  Scene/Node/Edge · draw · Layout · clip     │  ← f: render
                 │  Theme · NativeFeel · effects · chrome      │  ← f: theming
                 └───────────────────┬───────────────────────┘
   component families (each a crate, each an Elm+Facet):
     grid ─ dataview ─ graph ─ map ─ map3d ─ pipeline ─ plot ─ docview
                                     │
   app  (NavShell + Router + the demo deck that hosts them all)

Every family uses facett-core's four kernel functions (facet, elm, render, theming) and is driven by the fifth (harness). app uses every family. The kernel depends only on egui, serde, and its own modules — nothing downstream.

The functions

function what it is design
facet the host-facing component contract: Facet / FacetDeck / FacetCaps / clipboard facet-design.md
elm the internal component loop: Model/Msg/pure-view/update + the bridge macro + harness seam elm-design.md
render the CPU/GPU render kernel behind one draw() — Scene/Layout/clip, the wgpu fast path render-design.md
theming the unified look: Theme presets, platform-adaptive NativeFeel, effects, chrome theming-design.md
harness headless drive + snapshot + the test-matrix / robot seam harness-design.md
grid the flagship Arrow-backed virtualized data grid (+ the simpler table) grid-design.md
dataview browse + time-travel an Iceberg table; the warehouse deck dataview-design.md
graph node/edge visualizations: graph, the vello render engine, pan, 3D graph, system-map graph-design.md
map 2D geo: Web-Mercator map, scrollable geomap, GeoParquet ingest map-design.md
map3d 3D spatial: the 3D map (swappable RenderBackend) + the glTF model viewer map3d-design.md
pipeline the engine-agnostic dataflow/DAG viewer (+ plan-DAG) pipeline-design.md
plot charting: line/bar plots, statistical plotters charts, progress plot-design.md
docview the documentation viewer — a Typst manual as one SVG per page docview-design.md
app the application framework: NavShell + Router + nav widgets, and the demo deck app-design.md

The render kernel (one draw, CPU now, GPU behind it)

facett_core::draw is a CPU painter today; the wgpu fast path (GPU viewport-cull + indirect draw) lands behind the same draw() / Facet::ui, so consumers never change — they get GPU-fast for free. That single-seam rule is why the kernel is one crate everyone shares, and why a component's author writes to Scene / Layout and not to any backend. The full 2-category (CPU / CPU+GPU) design is render-design.md.

The headless spine

Because every component's whole observable truth is one Model (Elm) surfaced as state_json (Facet), a test can drive any component with a Msg script and assert the resulting Model/RenderReport — no window, no GPU. Robot testing and the nornir test-matrix are exactly this seam at scale: harness-design.md.