Add the flow editor: canvas, node panel and live values

The browser half of M3. Flows open on a full-bleed canvas with their chrome
floating over it: flow tabs top, dock bottom, node settings in a panel on the
right that leaves the graph visible and running behind it.

- Connections are derived, not stored. A node declares the messages it reads
  and publishes; every matching pair draws an edge, so two producers of one
  message converge on their consumer. Dragging output to input is shorthand
  for pointing that input at the producer's message, and asks before it
  replaces an existing one.
- Values land on the edges as they flow, over a websocket that feeds a store
  outside React, so a value arriving re-renders its own chip and nothing else.
  Clicking an edge shows the last payload and when it arrived.
- Node source is edited in Monaco, loaded only when a panel opens and themed
  from the design tokens.
- Edits autosave; identical documents are skipped server-side, so a quiet
  canvas writes nothing.
- Validation from the API shows on the node it belongs to and is summarised in
  the dock, where each entry pans to its node.
- Works on a phone: touch-connect, 44px dock targets, and the node panel
  becomes a full-screen sheet.

Two new tokens (--status-success, --font-mono) are mirrored in the website repo
and recorded in DESIGN-GUIDELINES.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WzrvW7rjQbynnhF6pxh6i
This commit is contained in:
Melvin Strobl
2026-08-15 18:10:50 +02:00
co-authored by Claude Fable 5
parent 06a4506767
commit 8c82549cf6
40 changed files with 5027 additions and 66 deletions
+25 -19
View File
@@ -30,28 +30,30 @@ Python, optimised for development speed. Owns the graph structure, persistence a
external interfaces. See `docs/architecture/structure.canvas`*Backend Management*.
- [x] FastAPI + SQLModel + Alembic + Postgres base with JWT auth and user management
- [x] Flow engine prototype in `backend/app/flow/`: `Node` / `Pipeline` / `StateBackend`
(memory + Redis) / `PipelineController` with `watchfiles` hot-reload
- [x] Flow engine in `backend/app/flow/`: `Node` / `Pipeline` / `StateBackend`
(memory + Redis) / `FlowController`
- [x] Node types: HTTP, MQTT, InfluxDB, Delay, MLP
- [ ] Make `app/flow` an importable package (`__init__.py`, absolute `app.flow.*` imports)
— nothing can consume it until this lands
- [ ] Typed, serializable node I/O: declared input/output schemas (Pydantic),
JSON-serializable messages with explicit binary codecs, no pickle in the
state backends
- [ ] Secrets/credentials store for node integrations managed via the API/UI;
- [x] `app/flow` is an importable package with absolute `app.flow.*` imports
- [x] Typed, serializable node I/O: every port declares a `DType`, messages are
JSON on the wire and in Redis, no pickle anywhere. Binary codecs are still
open — `DType.JSON` carries everything non-scalar for now
- [x] Message namespacing per flow (`flow.message`), with several producers per
message resolving to real fan-in
- [x] Secrets/credentials store for node integrations managed via the API/UI
(encrypted at rest, referenced from node params as `{"$secret": "name"}`);
`.env` bootstrap-only
- [ ] Connector node contract: declared I/O schemas, UI-driven credential and
setup flow, polling/discretization behaviour, health reporting, packaging
metadata — plus an authoring guide and skeleton repo. Device-specific
nodes are written against it as external plugins; the registry follows
later
- [ ] Persistence models for flows, nodes, edges and node source, replacing the
filesystem-and-hot-reload prototype
- [ ] REST + WebSocket API over the engine: create/read/update flows, run, stream results
- [ ] Dependency-loop detection and graph validation surfaced as API errors
- [ ] Redis / MQTT broker / InfluxDB compose services (blocked on the API wiring above —
no runtime path reaches them today)
- [ ] Git-based versioning of the in-memory flow database
- [x] Flow persistence: `flow.json` plus node sources per flow, replacing the
watch-directory prototype
- [x] REST + WebSocket API over the engine: create/read/update flows, edit node
source, run, and stream values, node status and execution events
- [x] Dependency-loop detection and graph validation surfaced as API errors
- [ ] MQTT broker / InfluxDB compose services for local development
- [x] Git-based versioning of the flow store (one commit per saved change)
- [ ] Import/export of a flow as human-readable code plus a JSON structure
- [ ] Per-input/-output discretization interval setting
- [ ] Alert / notification handler
@@ -80,13 +82,17 @@ React + Vite, primarily desktop but usable on mobile. See `docs/architecture/str
- [x] Dashboard SPA shell: TanStack Router, floating frosted sidebar, auth flows,
generated OpenAPI SDK
- [ ] Node canvas (`@xyflow/react`) showing nodes and connections
- [ ] Tab-style view of atomic flows, with a floating dock
- [ ] Embedded code editor (Monaco) for node source
- [x] Node canvas (`@xyflow/react`) showing nodes and their connections, which
are derived from message names rather than stored
- [x] Tab-style view of atomic flows, with a floating dock
- [x] Embedded code editor (Monaco) for node source
- [x] Live values on the edges, with the last payload and its time on click
- [x] Validation shown on the node it belongs to, and summarised in the dock
- [ ] Device assignment per node, selectable from compatible devices
- [ ] Test-node affordance on the canvas
- [ ] User management screens
- [ ] Mobile view for minor adjustments (PWA via `vite-plugin-pwa`)
- [x] Mobile-friendly canvas: touch connect, full-screen node panel
- [ ] Installable as a PWA (`vite-plugin-pwa`)
## Phase 4 — Frontend: dashboard view