substrate-ui
The console for substrate runs: rail, run-as-graph, topology-structure, event stream, inspector, verdict, diff, launch/resume, Studio. Vanilla JS. No bundler.
The three capabilities
OBSERVE · CONTROL · AUTHORA record rail; the run-as-graph (firing-anchored Producer-instance lifespans + spawn-cohort bands) and the static topology-structure view; the event stream; a provenance inspector; the health verdict; record diff; an I/O pane. One seq-cursor drives the graph + stream in lock-step.
Launch a bundled topology; resume a paused run; live-attach (follow a run as it's written). Launch + resume only — the UI never mutates run semantics.
The Studio: structured-form and drag-canvas authoring of Producers, Views, Triggers, Routes, and composed TerminationPolicies → live validation through the real TopologyBuilder → build and launch a genuine recorded run.
A thin, dependency-light stack — the runtime is the source of truth; the UI is a lens. Three capabilities on the real runtime: observe (record rail, run-as-graph, topology structure, event stream, provenance, verdict, diff, I/O); control (launch a bundled topology, resume a paused run, live-attach); and author (the Studio — form + drag-canvas authoring → live validation through the real TopologyBuilder → build and launch a genuine recorded run, deep-linked back to observe).
No web framework, no ORM, no frontend bundler, no CDN. Backend deps: Python stdlib + msgspec + substrate (installed library). The UI is its own git repo because it consumes substrate only as a library, through its public surfaces — never kernel internals.


server.py is the Python process — stdlib http.server + msgspec, HTTP routing plus read projections over substrate.api (records index, run_graph, topology_graph, summary, io, diff, explain). Thin control at /api/launch and /api/resume; the Studio seam at /api/validate and /api/build. Imports only substrate's public surfaces — no kernel internals. builder.py is the authoring translator: an authored JSON spec → a real topology(b) function.
The frontend (web/index.html + web/app.js) is the console — vanilla JS, no build step: rail, run-as-graph + topology-structure, stream, inspector, verdict, diff, I/O, launch/resume, live-follow.
That boundary is enforced by tests/test_server.py's import-boundary test, not just by convention. The runtime stays the source of truth; the UI reads it and shows it back.
