# 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, top to bottom on a phone — and the arrangement is recomputed as the graph changes. There is nothing to drag and nothing to tidy. That is on purpose. The edges come from message names, so a stored layout would be a second, weaker description of the same thing, and something to merge when two people edit the same flow. It also keeps flows honest: a graph nobody can hand-arrange is one worth splitting. 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 ⌘K / Ctrl-K 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](operations.md) 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](../concepts/values.md). **Timeout** (Function nodes) is how many seconds the code may run before it is stopped. Once a node streams, this becomes an *idle* timeout: it measures silence, not duration, so a node that yields every few seconds can run for hours under a timeout of 300. **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. 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. - **Mode** — `live` or `batch`. Live reacts to what arrives; batch only runs when a run asks it to. See [Runs](../concepts/runs.md). - **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 — 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 | |---|---| | ⌘K / Ctrl-K | 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 flow with any of these except the last does not run, and the health summary on Home counts it. ## See also - [Flows, nodes and messages](../concepts/flows.md) — the model behind the canvas - [Node types](../reference/node-types.md) — everything the palette offers - [Writing node code](../code/nodes.md) — what goes in the editor