{"id":"mcp-live","title":"MCP live (AI builds the graph)","category":"Showcases","description":"Start @xenolithengine/graph-mcp-server locally, click Connect, then ask Claude Desktop / Cursor to build a graph. The AI calls list_node_types → add_node → connect_pins → auto_layout. \"I describe it, the editor builds it.\"","url":"https://xenolithengine.github.io/xenolith-graph/examples/mcp-live/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/mcp-live/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/mcp-live.jpg","frameworks":["react"],"files":["demos/MCPDemo.tsx"]}
{"id":"step-debugger","title":"Visual stepping debugger","category":"Showcases","description":"Run a graph one node at a time. Yellow ring = paused; green = executed; red = breakpoint. The inspector shows live inputs/outputs and per-node timing. Debug your AI workflow on the canvas — like Chrome DevTools, but for nodes.","url":"https://xenolithengine.github.io/xenolith-graph/examples/step-debugger/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/step-debugger/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/step-debugger.jpg","frameworks":["react"],"files":["demos/StepDebuggerDemo.tsx"]}
{"id":"time-travel","title":"Time-travel scrubber","category":"Showcases","description":"Rewind a graph run. Drag the timeline through every step and watch the highlights replay — green = done, yellow = the step under inspection. The inspector shows that step’s inputs and outputs.","url":"https://xenolithengine.github.io/xenolith-graph/examples/time-travel/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/time-travel/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/time-travel.jpg","frameworks":["react"],"files":["demos/TimeTravelDemo.tsx"]}
{"id":"graph-diff","title":"Graph diff (PR review)","category":"Showcases","description":"Two versions of a graph side by side, with structural diff highlights — green = added, red = removed, yellow = modified. Drop-in PR-review for node graphs.","url":"https://xenolithengine.github.io/xenolith-graph/examples/graph-diff/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/graph-diff/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/graph-diff.jpg","frameworks":["react"],"files":["demos/GraphDiffDemo.tsx"]}
{"id":"heatmap","title":"Per-node cost heatmap","category":"Showcases","description":"A RAG pipeline with per-node latency badges — cool blue → hot red. Press Pulse to see metrics breathe. Drop-in observability overlay; no OSS competitor ships it.","url":"https://xenolithengine.github.io/xenolith-graph/examples/heatmap/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/heatmap/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/heatmap.jpg","frameworks":["react"],"files":["demos/HeatmapDemo.tsx"]}
{"id":"llm-builder","title":"LLM workflow builder","category":"Showcases","description":"Input → Prompt → Model → Output. Press Run; the chain walks in topological order, the active node glows, the completion streams into the Output. A prettier LangFlow, on Xenolith.","url":"https://xenolithengine.github.io/xenolith-graph/examples/llm-builder/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/llm-builder/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/llm-builder.jpg","frameworks":["react"],"files":["shared/llm-builder.json","demos/LLMBuilderDemo.tsx","shared/llm-builder.ts"]}
{"id":"audio-synth","title":"Audio synth (Web Audio)","category":"Showcases","description":"A real synth built on the graph — Oscillator → Filter → Gain → Output. Knobs are node widgets; Play wires live AudioNodes and lights the active chain. It makes sound.","url":"https://xenolithengine.github.io/xenolith-graph/examples/audio-synth/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/audio-synth/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/audio-synth.jpg","frameworks":["react"],"files":["shared/audio-synth.json","demos/AudioSynthDemo.tsx","shared/audio-synth.ts"]}
{"id":"save-restore","title":"Save & restore","category":"Showcases","description":"The whole graph is JSON. Download / upload a .json file, and autosave to localStorage on every edit (driven by useGraphJSON). Reload the page — it comes back.","url":"https://xenolithengine.github.io/xenolith-graph/examples/save-restore/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/save-restore/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/save-restore.jpg","frameworks":["react","vue","svelte","solid","angular"],"files":["demos/SaveRestoreDemo.tsx","shared/save-restore.ts","vue/SaveRestoreDemo.vue","vue/SavePanel.vue","shared/save-restore.ts","vanilla/svelte-save-restore.ts","shared/save-restore.ts","vanilla/solid-save-restore.ts","shared/save-restore.ts","angular/SaveRestoreDemo.component.ts","shared/save-restore.ts"]}
{"id":"image-pipeline","title":"Image pipeline (WebGL)","category":"Showcases","description":"A real image-filter pipeline — Source → Exposure → Saturation → Hue → Blur → Vignette → Result. Each node is a live GLSL fragment pass. Drag a slider and the result re-renders; drop your own image; download the PNG.","url":"https://xenolithengine.github.io/xenolith-graph/examples/image-pipeline/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/image-pipeline/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/image-pipeline.jpg","frameworks":["react"],"files":["demos/ImagePipelineDemo.tsx","shared/image-pipeline.ts"]}
{"id":"mount","title":"Mount an editor","category":"Nodes","description":"The honest minimum: register a node type, add one, frame it. Xen is the default theme — no setup.","url":"https://xenolithengine.github.io/xenolith-graph/examples/mount/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/mount/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/mount.jpg","frameworks":["react","vue","svelte","solid","angular"],"files":["shared/mount.json","demos/MountDemo.tsx","shared/mount.ts","vue/MountDemo.vue","shared/mount.ts","vanilla/svelte-mount.ts","shared/mount.ts","vanilla/solid-mount.ts","shared/mount.ts","angular/MountDemo.component.ts","shared/mount.ts"]}
{"id":"load","title":"Load a graph","category":"Nodes","description":"Load a real saved xenolith.v1 graph and reframe it. Built-in controls + a reload panel.","url":"https://xenolithengine.github.io/xenolith-graph/examples/load/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/load/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/load.jpg","frameworks":["react"],"files":["demos/LoadDemo.tsx","shared/scene.ts"]}
{"id":"builtin-widgets","title":"Built-in widgets","category":"Widgets","description":"Every built-in widget — slider, number, toggle, combo, color, text — on one node, in WebGL.","url":"https://xenolithengine.github.io/xenolith-graph/examples/builtin-widgets/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/builtin-widgets/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/builtin-widgets.jpg","frameworks":["react"],"files":["shared/builtin-widgets.json","demos/BuiltinWidgetsDemo.tsx","shared/builtin-widgets.ts"]}
{"id":"canvas-widget","title":"Custom canvas widget","category":"Widgets","description":"The simplest custom widget: a click/drag level bar, drawn in WebGL — no DOM. The value flows back to your app via the standard widget callback.","url":"https://xenolithengine.github.io/xenolith-graph/examples/canvas-widget/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/canvas-widget/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/canvas-widget.jpg","frameworks":["react"],"files":["shared/canvas-widget.json","demos/CanvasWidgetDemo.tsx","shared/canvas-widget.ts"]}
{"id":"custom-widgets","title":"Bring your own UI","category":"Widgets","description":"Four widgets that are real framework components (async-select, file drop, CodeMirror, sparkline), themed via --xeno-*.","url":"https://xenolithengine.github.io/xenolith-graph/examples/custom-widgets/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/custom-widgets/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/custom-widgets.jpg","frameworks":["react"],"files":["demos/CustomWidgetsDemo.tsx","widgets/AsyncSelect.tsx","widgets/FileDrop.tsx","widgets/CodeEditor.tsx","widgets/Sparkline.tsx"]}
{"id":"events","title":"Events → your state","category":"Interaction","description":"Typed event callbacks wired to app state: a live log, selection inspector, widget values.","url":"https://xenolithengine.github.io/xenolith-graph/examples/events/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/events/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/events.jpg","frameworks":["react","vue","svelte","solid","angular"],"files":["demos/EventsDemo.tsx","vue/EventsDemo.vue","vue/EventsPanel.vue","vanilla/svelte-events.ts","vanilla/solid-events.ts","angular/EventsDemo.component.ts"]}
{"id":"mobile-touch","title":"Mobile / tablet (touch demo)","category":"Interaction","description":"Touch-first demo for testing pinch, two-finger pan, long-press context menu, and the drawer-mode palette on narrow viewports. Includes a fullscreen toggle. Open this URL on an iOS device or in the iOS Simulator — see docs/TESTING-ON-IOS-SIMULATOR.md.","url":"https://xenolithengine.github.io/xenolith-graph/examples/mobile-touch/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/mobile-touch/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/mobile-touch.jpg","frameworks":["vanilla"],"files":["vanilla/mobile-touch.ts"]}
{"id":"conditional-widgets","title":"Conditional widgets","category":"Widgets","description":"Declarative `displayOptions.show(state)` — n8n-style. One HTTP Request node hides `body` until the method needs one, and `token` until auth is `bearer`. Pure schema: no `setNodeWidgets` plumbing in the host. The node re-layouts and edges stay attached as widgets appear and disappear.","url":"https://xenolithengine.github.io/xenolith-graph/examples/conditional-widgets/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/conditional-widgets/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/conditional-widgets.jpg","frameworks":["vanilla","react"],"files":["vanilla/conditional-widgets.ts","shared/conditional-widgets.ts","demos/ConditionalWidgetsDemo.tsx","shared/conditional-widgets.ts"]}
{"id":"properties-sidebar","title":"Properties sidebar","category":"Interaction","description":"A \"fat\" node with 8 widgets opts into the docked properties panel via the per-widget `showInSidebar: true` flag. Edit live — the same widget renders inline AND in the panel; no separate sidebar component to author. Themed via --xeno-*. Open programmatically: `editor.openSidebar(nodeId)`.","url":"https://xenolithengine.github.io/xenolith-graph/examples/properties-sidebar/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/properties-sidebar/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/properties-sidebar.jpg","frameworks":["vanilla","react","vue","svelte","solid","angular"],"files":["vanilla/properties-sidebar.ts","shared/properties-sidebar.ts","demos/PropertiesSidebarDemo.tsx","shared/properties-sidebar.ts","vue/PropertiesSidebarDemo.vue","vue/SidebarTogglePanel.vue","shared/properties-sidebar.ts","vanilla/svelte-properties-sidebar.ts","shared/properties-sidebar.ts","vanilla/solid-properties-sidebar.ts","shared/properties-sidebar.ts","angular/PropertiesSidebarDemo.component.ts","shared/properties-sidebar.ts"]}
{"id":"two-way","title":"Two-way data binding","category":"Interaction","description":"Both binding levels in one: `useSelection()` edits the selected node’s widgets; `useGraphJSON()` binds the whole graph ⇄ JSON. No manual event wiring.","url":"https://xenolithengine.github.io/xenolith-graph/examples/two-way/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/two-way/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/two-way.jpg","frameworks":["react"],"files":["demos/TwoWayBindingDemo.tsx"]}
{"id":"diagram","title":"Diagram edges","category":"Showcases","description":"Edges as a diagramming primitive — text nodes wired with directional arrowhead markers, edge labels (pass / fail / retry), and an animated flowing dash on the main path. Toggle the flow.","url":"https://xenolithengine.github.io/xenolith-graph/examples/diagram/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/diagram/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/diagram.jpg","frameworks":["react"],"files":["shared/diagram.json","demos/DiagramDemo.tsx","shared/diagram.ts"]}
{"id":"type-conversions","title":"Type conversions","category":"Interaction","description":"Typed pins of different types refuse to connect — unless you register a conversion. NumberSource (out: number) won’t wire into TextSink (in: text) until `types.registerConversion(\"number\", \"text\", String)` is called. Toggle the cast live; the existing edge drops when it disappears.","url":"https://xenolithengine.github.io/xenolith-graph/examples/type-conversions/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/type-conversions/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/type-conversions.jpg","frameworks":["vanilla","react"],"files":["vanilla/type-conversions.ts","shared/type-conversions.ts","demos/TypeConversionsDemo.tsx","shared/type-conversions.ts"]}
{"id":"breadcrumb-dive","title":"Subgraph breadcrumb","category":"Interaction","description":"Nested template instances (Pipeline → Stage → primitives). Dive in by double-click OR programmatically; the breadcrumb in the top-left tracks the path (Root › Pipeline › Stage) and pops any segment. Auto-themed via --xeno-*. Opt-out with `editor.setBreadcrumbVisible(false)`.","url":"https://xenolithengine.github.io/xenolith-graph/examples/breadcrumb-dive/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/breadcrumb-dive/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/breadcrumb-dive.jpg","frameworks":["vanilla","react"],"files":["vanilla/breadcrumb-dive.ts","shared/breadcrumb-dive.ts","demos/BreadcrumbDiveDemo.tsx","shared/breadcrumb-dive.ts"]}
{"id":"palette-sidebar","title":"Palette sidebar (drag to spawn)","category":"Interaction","description":"16 schemas across 5 categories (data / math / transform / logic / io) listed in a docked palette on the left. Drag any tile onto the canvas — the editor inserts the node at the drop point via its built-in `node:drop` handler. Configure with `editor.setPaletteSidebar({ side, filter })`.","url":"https://xenolithengine.github.io/xenolith-graph/examples/palette-sidebar/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/palette-sidebar/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/palette-sidebar.jpg","frameworks":["vanilla","react","vue","svelte","solid","angular"],"files":["vanilla/palette-sidebar.ts","shared/palette-sidebar.ts","demos/PaletteSidebarDemo.tsx","shared/palette-sidebar.ts","vue/PaletteSidebarDemo.vue","shared/palette-sidebar.ts","vanilla/svelte-palette-sidebar.ts","shared/palette-sidebar.ts","vanilla/solid-palette-sidebar.ts","shared/palette-sidebar.ts","angular/PaletteSidebarDemo.component.ts","shared/palette-sidebar.ts"]}
{"id":"connection-validation","title":"Connection validation","category":"Interaction","description":"Typed Blueprint pins refuse mismatched wires automatically (a string won’t plug into a number). A custom guard adds cycle prevention on top. Every attempt is logged live.","url":"https://xenolithengine.github.io/xenolith-graph/examples/connection-validation/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/connection-validation/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/connection-validation.jpg","frameworks":["react"],"files":["shared/connection-validation.json","demos/ConnectionValidationDemo.tsx","shared/connection-validation.ts"]}
{"id":"export-image","title":"Export to image","category":"Interaction","description":"Export the whole graph — not just the viewport — to a Blob at any scale. Download PNG, retina 2×, or JPG straight from a panel.","url":"https://xenolithengine.github.io/xenolith-graph/examples/export-image/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/export-image/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/export-image.jpg","frameworks":["react"],"files":["demos/ExportImageDemo.tsx","shared/export-image.ts"]}
{"id":"preview-nodes","title":"Per-node canvas drawing","category":"Widgets","description":"Sparkline + ColorPreview nodes — each paints its own body via a CanvasWidgetController (the equivalent of LiteGraph onDrawForeground). The sparkline rolls a live plot of the upstream slider; the swatch fills from `node.state.tint`. Anything you can draw on a `<canvas>` can be a node body.","url":"https://xenolithengine.github.io/xenolith-graph/examples/preview-nodes/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/preview-nodes/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/preview-nodes.jpg","frameworks":["vanilla","react"],"files":["vanilla/preview-nodes.ts","shared/preview-nodes.ts","demos/PreviewNodesDemo.tsx","shared/preview-nodes.ts"]}
{"id":"edge-paths","title":"Edge path styles","category":"Styling","description":"Per-edge `pathStyle`: bezier (default Xen S-curve), smoothstep (rounded orthogonal), step (90° elbows), linear (straight). Set on construction or live via `editor.setEdgeOptions(id, { pathStyle })`. Same wire colour / animated dash / arrowhead contract regardless of shape.","url":"https://xenolithengine.github.io/xenolith-graph/examples/edge-paths/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/edge-paths/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/edge-paths.jpg","frameworks":["vanilla","react"],"files":["vanilla/edge-paths.ts","shared/edge-paths.ts","demos/EdgePathsDemo.tsx","shared/edge-paths.ts"]}
{"id":"theming","title":"Theming","category":"Styling","description":"Theme is a reactive prop — flip Xen ⇄ Liquid Glass at runtime; panels/widgets restyle via --xeno-*.","url":"https://xenolithengine.github.io/xenolith-graph/examples/theming/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/theming/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/theming.jpg","frameworks":["react"],"files":["demos/ThemingDemo.tsx"]}
{"id":"nested-layout","title":"Nested auto-layout (ELK)","category":"Layout","description":"Three levels of nested macros — Encoder/Decoder containing Attention/FFN containing leaf ops. ELK respects the hierarchy (children stay inside their parent frame); dagre ignores parent and pancakes everything. Toggle to see the difference.","url":"https://xenolithengine.github.io/xenolith-graph/examples/nested-layout/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/nested-layout/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/nested-layout.jpg","frameworks":["vanilla","react"],"files":["vanilla/nested-layout.ts","shared/nested-layout.ts","demos/NestedLayoutDemo.tsx","shared/nested-layout.ts"]}
{"id":"auto-layout","title":"Auto-layout (dagre)","category":"Layout","description":"A messy 14-node DAG snaps into a clean layered layout. Toggle LR/TB; Cmd+Z restores the mess in a single undo step.","url":"https://xenolithengine.github.io/xenolith-graph/examples/auto-layout/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/auto-layout/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/auto-layout.jpg","frameworks":["vanilla","react"],"files":["vanilla/auto-layout.ts","shared/auto-layout.ts","demos/AutoLayoutDemo.tsx","shared/auto-layout.ts"]}
{"id":"viewport","title":"Viewport & minimap","category":"Viewport","description":"Built-in controls (zoom/fit/reset/undo/redo/save/lock), toggleable minimap, live useNodes/useViewport readout.","url":"https://xenolithengine.github.io/xenolith-graph/examples/viewport/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/viewport/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/viewport.jpg","frameworks":["react"],"files":["demos/ViewportDemo.tsx"]}
{"id":"stress-test","title":"Stress test (1000s of nodes)","category":"Showcases","description":"Generate hundreds → thousands of WebGL nodes wired into a chain. Live FPS + node-count overlay top-right; the panel counter is driven by the reactive `useNodes()` hook. Zoom floor dropped to 5% so 10k+ nodes fit on one screen.","url":"https://xenolithengine.github.io/xenolith-graph/examples/stress-test/","llmsUrl":"https://xenolithengine.github.io/xenolith-graph/examples/stress-test/llms.md","thumb":"https://xenolithengine.github.io/xenolith-graph/examples/thumbs/stress-test.jpg","frameworks":["react"],"files":["demos/StressTestDemo.tsx","shared/stress-test.ts"]}
