Files
stroblmeandClaude Opus 5 bdad6d7fc2
Docs / docs (push) Successful in 37s
Playwright Tests / test-playwright (1, 2) (push) Failing after 1m35s
Playwright Tests / test-playwright (2, 2) (push) Failing after 17s
pre-commit / pre-commit (push) Failing after 2m8s
Test Backend / test-backend (push) Failing after 2m48s
Compose Smoke Test / test-compose (push) Failing after 13s
Playwright Tests / merge-reports (push) Failing after 2m25s
Make the docs state things rather than argue them
The site read as a design journal: rationale paragraphs, hedges
("deliberately", "on purpose", "genuinely"), meta-commentary about the docs
themselves, and one em-dash every ten lines carrying an aside.

Roughly twenty rationale blocks are gone or reduced to what a reader needs
in order to use the thing. Em-dashes go from 507 to 135, and what is left is
structural rather than prose: list and definition separators, table cells,
and four inside code blocks that quote what the CLI actually prints.

Also: api.example.com becomes api.fluksio.com (the emails stay, since
bootstrap.py really defaults to admin@example.com and RFC 2606 reserves it);
the mqtt table gains the two settings it had drifted behind on and inject's
wording matches the engine; llms.txt lists the two connector pages that were
in the nav but not in it; and the two device/device_policy notes now agree.

Builds clean under `zensical build --strict`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YrQnKV3bnQd4K342y8tKj
2026-08-31 10:49:58 +02:00

6.5 KiB

The flow editor

The canvas is where most of the work happens. It floats its chrome over a full-bleed graph, so what you are looking at is always the flow.

The canvas

Nodes are laid out for you, left to right on a desktop and top to bottom on a phone, and the arrangement is recomputed as the graph changes. There is nothing to drag and nothing to tidy.

The edges come from message names, so there is no layout to store or to merge when two people edit the same flow.

What is drawn:

  • Your nodes, with a status dot — running, succeeded, failed, or nothing at all when idle. Status is always named in words too, never colour alone.
  • Edges, which pulse when a value goes down them. Click one to inspect it.
  • Endpoints — anything wired into this flow that is not a node in it: a dashboard control writing a message, a tile reading one, a node in another flow on the far side of a dotted name. Drawn as labelled boxes at the boundary, so a value never appears to come from nowhere.

Values are live. The editor holds a websocket to the engine, and the connection banner tells you when it is not.

Adding a node

Add node on the dock, or ⌘P / Ctrl-P for the command palette, which also jumps between flows and offers your shared nodes. Pick a type and it appears on the canvas with its panel open.

The node panel

Floats on the right; a full-screen sheet on a phone.

Consumes and Provides are the ports. Each row is a message name, a payload type, and, on an output, a streaming toggle for ports that publish repeatedly during one execution. The name field suggests messages already in the flow, which is usually how you wire something: type the name that already exists.

Renaming an output renames the message everywhere it is read. Inputs are not renamed, because an input is more often re-pointed at a different message than renamed.

Settings is generated from the node type's parameter schema, so an MQTT node shows broker, topic and QoS, and an ntfy node shows server, topic and priority. A field marked as a credential renders as a picker over your stored secrets instead of a text box.

A Function node gets a second settings section where you add your own: a setting is a constant of this node's code and arrives as an argument beside its ports. See Where a node's values come from.

Timeout (Function nodes) is how many seconds the code may be silent before it is stopped: it measures silence, not duration, so a node that yields every few seconds can run for hours under a timeout of 300. Left empty there is no limit, which is the default. Set one where a node going quiet means it is stuck rather than working. A 0 says so explicitly.

Code is the editor. It saves as you type and applies on ⌘S; the node reloads without the flow stopping. A node file defines process(...); if it defines exactly one public function under another name, that one is used instead.

Shared turns a node's code into a library entry other flows can reuse. Editing a shared node edits the copy every flow using it runs, which is the point and also the caution.

!!! note "Not in the panel yet"

`device` and `device_policy`, which machine a node's code runs on, are set
through the API rather than the panel, with `PUT /flows/{name}`. See
[Remote workers](../code/workers.md).

The flow panel

Click the canvas title to open the flow's own settings.

  • Running — the switch that starts and stops the flow. Stopped means none of its subscriptions, schedules or webhooks exist.
  • Modelive or batch. Live reacts to what arrives; batch only runs when a run asks it to. See Runs.
  • Inputs — messages the flow takes from outside, with the value each starts from. For a batch flow these are also the run's parameters.
  • Outputs (batch only) — which messages a run reports as its result.
  • Contents — a reminder that this flow's name namespaces every message inside it.

Inspecting an edge

Click a wire. You get the last payload that went down it, when, and a sparkline of its recent numeric history. You can also republish that value from the node that produced it, which re-runs everything downstream. It is the fastest way to test a change without waiting for the real sensor.

The dock

Along the bottom, floating over the canvas.

Control What it does
Add node opens the palette
Fit returns to the view the flow opened with
Run injects a value by hand; on a batch flow, opens the parameters dialog
Pause / Resume holds messages instead of running them
Step releases exactly one held message
Publish puts the draft live
Discard throws the draft away
Issues what is stopping this flow from running, per node
Logs what the nodes printed, filterable

Pause and step together are how you test a flow before it moves anything physical: pause it, inject a value, step it through, watch the values appear on the edges, then publish.

Shortcuts

Chord Action
⌘P / Ctrl-P command palette
⌘S / Ctrl-S publish the flow — or, with focus in the code editor, apply the code
⌘Z / ⌘⇧Z undo / redo (the flow; the code editor has its own)
⌘C / ⌘V copy and paste nodes, including between flows

Drafts and publishing

Saving writes a draft; the engine keeps running what was published. Publishing promotes it and reloads.

If someone else saved the same flow while you were working, publishing answers with a conflict rather than overwriting them. The Flows list offers Publish all changes when several flows are sitting on drafts.

Issues

The canvas validates as you edit and marks the node each issue belongs to:

  • a port that needs a message nothing in reach provides
  • a message that exists but has never held a value
  • a dependency cycle
  • a node reading a message it also writes, with nothing to start it from
  • code that did not load
  • a webhook with no shared secret (advisory — it does not stop the flow)
  • a node that loaded but reports itself down, such as a connector that cannot reach its device

A flow with any of these except the last two does not run, and the health summary on Home counts it. The last one clears on its own once the node reports itself well again.

See also