Bitfocus AS
logo
logo
Bitfocus AS
logo
logo
Sign upSign in

Loading...

Bitfocus

Subscribe to our newsletter

The latest news, articles, and resources, sent to your inbox.

FacebookInstagramGitHubYouTubeLinkedIn

Products

  • Buttons
  • Companion

Integrations

  • Supported Devices
  • Developer Community
  • Connection Development

Support

  • Support Overview
  • Documentation
  • Video Tutorials
  • Community Forum

Sales

  • Resellers & Integrators
  • Buttons Pricing

Updates

  • Case Studies
  • Events & Trade Shows
  • Press Releases
  • Product Updates
  • Webinars

Legal

  • Legal Overview
  • Privacy Policy
  • Buttons EULA
  • Terms & Cookie Policy

Company

  • About us
  • Press kit
  • Careers

© 2026 Bitfocus AS. All rights reserved.

Workflow node reference
Docs for
Buttons overview
Adding a License
Offline License
Debian/Ubuntu-headless build of Bitfocus Buttons
Position
Basic Section
Shift Section
Folder Section
Popover Section
Router Section v1.4.x
Router Section v1.6.x
Shared Section
Button
Presets
Internal Actions
Connect
Connection
NMOS
Surface
Workflow
Workflow Examples
Workflow node reference
Cuelist
Tags
Routing
Auth
SSO
Settings
Certificate
Network ports reference
Variables
Functions Reference
Functions
Operators

Loading...

Previous
← Workflow Examples
Next
Cuelist →
Contact support →
Buttons/Workflow/Workflow node reference

Workflow node reference


ActionNode#

The ActionNode executes actions on connections, triggering them based on configurable conditions: on startup, when data changes, or when an event is received.

Features#

  • Flexible Triggering: Trigger on startup, data change, or incoming event
  • Dynamic Options: Action options are validated against the action's own schema
  • Input Overrides: Connection ID and action key can be overridden from inputs
  • Change Detection: Tracks previous data to only fire when inputs actually change

Usage#

Trigger on Event#

Connect a trigger signal to the trigger input and enable triggerOnEvent. The action fires each time a trigger event arrives.

Trigger on Change#

Enable triggerOnChange. The action fires whenever any input value changes.

Trigger on Startup#

Enable triggerOnStartup. The action fires once when the workflow starts.

Node Structure#

Config Schema#

  • connectionId (string, optional): ID of the connection to run the action on
  • actionKey (string, optional): Key identifying the action to execute
  • triggerOnEvent (boolean, optional): Fire when a trigger event is received
  • triggerOnStartup (boolean, optional, default: false): Fire on workflow startup
  • triggerOnChange (boolean, optional, default: false): Fire when inputs change
  • Additional action-specific option fields

Input Schema#

  • trigger (optional): Trigger signal — fires the action when an event arrives
  • connectionId (string, optional): Override the configured connection ID
  • actionKey (string, optional): Override the configured action key
  • Additional passthrough fields for action options

Output Schema#

  • (no outputs)

Implementation Details#

  • Merges input values with config values; inputs take precedence
  • Validates action option inputs dynamically against the action definition's schema
  • Executes via RPC with a 5000ms timeout
  • Subscribes to action feedback after execution

Integration#

The ActionNode is registered in:
  • NodeRegistry as action
  • NodeTypeSchema as 'action'

Example Workflow Usage#

  1. PTZ Camera Control: Connect a button press to trigger, configure the connection and action key for pan/tilt
  2. Startup Initialisation: Enable triggerOnStartup to send an init command when the workflow loads
  3. Reactive Control: Enable triggerOnChange and wire a variable so the action fires whenever the variable changes

ButtonNode#

The ButtonNode provides a clickable UI button inside the workflow editor. Pressing it emits a trigger event that can be used to kick off downstream logic.

Features#

  • UI Interaction: Button is clickable directly in the workflow editor canvas
  • Event Emission: Publishes a trigger event on press, driving downstream nodes
  • Timestamp Output: Exposes the timestamp of the last press as a state value

Usage#

Place a ButtonNode on the canvas and connect its timestamp output (or trigger event handle) to any node that accepts a trigger input, such as an ActionNode or DelayNode.

Node Structure#

Config Schema#

  • (no configuration)

Input Schema#

  • (no inputs)

Output Schema#

  • timestamp (number): Unix timestamp (ms) of the most recent button press

Implementation Details#

  • Responds to the press UI action
  • Publishes a trigger event immediately on press
  • Calls workflow.rerenderFromNode() so downstream nodes update synchronously

Integration#

The ButtonNode is registered in:
  • NodeRegistry as button
  • NodeTypeSchema as 'button'

Example Workflow Usage#

  1. Manual Trigger: Use as a manual start button to kick off a sequence of actions
  2. Test Harness: Wire a ButtonNode to any chain to manually drive it during development

CaseSwitchNode#

The CaseSwitchNode is a workflow node that acts as a conditional router, passing through input values based on a conditional match. It's similar to a switch statement in programming languages.

Features#

  • Conditional Routing: Routes input based on a conditional value match
  • Dynamic Input Cases: Supports multiple input cases with configurable conditions
  • First Match Wins: Returns the first input case that matches the condition
  • No Match Handling: Returns undefined when no condition matches
  • Default Fallback: Optional default input is returned when no case matches

Usage#

Basic Switch#

Conditional Input: "yes"
Cases:
- case1: condition="yes", input="Hello"
- case2: condition="no", input="Goodbye"

Result: "Hello" (first match)

Multiple Cases#

Conditional Input: "red"
Cases:
- case1: condition="red", input="Stop"
- case2: condition="yellow", input="Caution"
- case3: condition="green", input="Go"

Result: "Stop" (matches "red")

No Match (with Default)#

Conditional Input: "blue"
Cases:
- case1: condition="red", input="Stop"
- case2: condition="yellow", input="Caution"
Default: input="Unknown"

Result: "Unknown" (no case matched, returned default)

Node Structure#

Input Schema#

  • conditional (required): The value to match against case conditions
  • case1, case2, ..., caseN (dynamic): Input values for each case
  • default (optional): Fallback value used when no case matches

Config Schema#

  • label (optional): Custom label for the node
  • enabled (default: true): Whether the node is enabled
  • inputVariables (array): Array of case configurations
    • name (string): Case name (used as input handle ID)
    • description (optional): Case description
    • condition (string): Condition value to match against

Output Schema#

  • result: The matched input value (or undefined if no match)
  • matched (boolean): Whether a match was found
  • matchedIndex (number, optional): Index of the matched case

Implementation Details#

The CaseSwitchNode works by:
  1. Converting the conditional input to a string
  2. Iterating through all configured cases in order
  3. Comparing each case's condition with the conditional value
  4. Returning the first matching case's input value
  5. If no match is found, returning undefined (or the default input if provided)

Integration#

The CaseSwitchNode is registered in:
  • NodeRegistry as caseSwitch
  • NodeTypeSchema as 'caseSwitch'

Example Workflow Usage#

  1. Status Router: Route different status messages based on a status code
  2. Language Selector: Route content based on language preference
  3. Error Handler: Route different error responses based on error type
  4. Menu System: Route to different menu options based on user selection

Comparison with Other Nodes#

  • LogicNode: Performs boolean operations, CaseSwitchNode routes based on value matching
  • WorkflowRouter: Routes entire workflows, CaseSwitchNode routes individual values
  • ExpressionNode: Evaluates expressions, CaseSwitchNode performs conditional routing

ChangeSwitchNode#

The ChangeSwitchNode watches a boolean input and records timestamps whenever the value transitions between true and false. It acts as a change detector with separate outputs for each transition direction.

Features#

  • Change Detection: Only updates outputs when the boolean value actually changes
  • Dual Timestamp Outputs: Separate outputs for the last true transition and last false transition
  • State Preservation: Remembers the last value and timestamps across renders

Usage#

Connect a boolean signal to valueA. The trueResult output updates with the current timestamp each time the value transitions to true, and falseResult updates when it transitions to false.
Input: false → true → true → false
trueResult: [updated] [unchanged]
falseResult: [unchanged] [updated]

Node Structure#

Config Schema#

  • (no configuration)

Input Schema#

  • valueA (boolean, optional): Boolean value to monitor

Output Schema#

  • trueResult (number): Timestamp (ms) of the last transition to true
  • falseResult (number): Timestamp (ms) of the last transition to false

Implementation Details#

  • Stores lastValue, lastTrueResult, and lastFalseResult in node state
  • Compares incoming value to lastValue; if identical, outputs are unchanged
  • Does not emit events — use ChangeSwitchNodeV2 if event-driven behaviour is needed

Comparison with ChangeSwitchNodeV2#

Feature
ChangeSwitchNode
ChangeSwitchNodeV2
State-based output
✓
✓
Emits events on change
✗
✓

Integration#

The ChangeSwitchNode is registered in:
  • NodeRegistry as changeSwitch
  • NodeTypeSchema as 'changeSwitch'

Example Workflow Usage#

  1. Edge Detection: Detect rising and falling edges of a boolean feedback value
  2. Timestamp Logging: Record when a signal last went high or low

ChangeSwitchNodeV2#

The ChangeSwitchNodeV2 is the event-emitting version of ChangeSwitchNode. It watches a boolean input and both updates timestamp outputs and emits events whenever the value transitions between true and false.

Features#

  • Change Detection: Only reacts when the boolean value actually changes
  • Dual Timestamp Outputs: Separate outputs for the last true and false transitions
  • Event Emission: Publishes trueResult or falseResult events on each transition, enabling reactive downstream processing

Usage#

Connect a boolean signal to valueA. On each true transition a trueResult event fires; on each false transition a falseResult event fires. Both events carry the current timestamp.
Input: false → true → true → false
Events emitted: trueResult falseResult

Node Structure#

Config Schema#

  • (no configuration)

Input Schema#

  • valueA (boolean, optional): Boolean value to monitor

Output Schema#

  • trueResult (number): Timestamp (ms) of the last transition to true
  • falseResult (number): Timestamp (ms) of the last transition to false

Output Events#

  • trueResult: Emitted when value transitions to true
  • falseResult: Emitted when value transitions to false

Implementation Details#

  • Behaves identically to ChangeSwitchNode with the addition of event publishing
  • Calls workflow.rerenderFromNode() on each transition so downstream nodes react immediately
  • Both output handles are event handles (isOutputHandleEvent() returns true for both)

Comparison with ChangeSwitchNode#

Feature
ChangeSwitchNode
ChangeSwitchNodeV2
State-based output
✓
✓
Emits events on change
✗
✓

Integration#

The ChangeSwitchNodeV2 is registered in:
  • NodeRegistry as changeSwitchV2
  • NodeTypeSchema as 'changeSwitchV2'

Example Workflow Usage#

  1. Trigger on Rising Edge: Connect the trueResult event to an ActionNode to fire an action only when the signal goes high
  2. Toggle Animations: Use trueResult / falseResult events to start/stop different sequences

ClampNode#

The ClampNode constrains a numeric value to stay within a configured minimum and maximum range.

Features#

  • Value Clamping: Ensures the output never exceeds max or falls below min
  • Configurable Bounds: Both bounds are set in config and validated (min must be ≤ max)
  • Type Coercion: String inputs are coerced to numbers before clamping

Usage#

min: 0, max: 100, value: 150 → result: 100
min: 0, max: 100, value: -10 → result: 0
min: 0, max: 100, value: 50 → result: 50

Node Structure#

Config Schema#

  • min (number, default: 0): Lower bound
  • max (number, default: 1, must be ≥ min): Upper bound

Input Schema#

  • value (unknown, coerced to number, optional): Value to clamp

Output Schema#

  • result (number): Clamped value

Implementation Details#

  • Uses Math.min(Math.max(value, min), max)
  • Validation rejects configs where min > max

Integration#

The ClampNode is registered in:
  • NodeRegistry as clamp
  • NodeTypeSchema as 'clamp'

Example Workflow Usage#

  1. Volume Control: Clamp a volume level to 0–100 before sending it to a mixer
  2. Safe Range: Ensure a position or speed value never exceeds hardware limits
 

ConnectionVariableNode#

The ConnectionVariableNode reads the current value of a variable from a specific connection and subscribes to live updates whenever that variable changes.

Features#

  • Live Variable Subscription: Automatically updates whenever the connection variable changes
  • Reactive: Triggers a workflow re-render on each update
  • Config-Driven: Connection ID and variable key are set in config and can be changed at runtime

Usage#

Configure the connectionId and variableKey. The value output will reflect the current value of that variable, updating automatically as the connection reports changes.

Node Structure#

Config Schema#

  • connectionId (string): ID of the connection to read from
  • variableKey (string): Key of the variable to read

Input Schema#

  • (no inputs)

Output Schema#

  • value (string | number | boolean | null | undefined): Current value of the variable

Implementation Details#

  • Subscribes to variable changes via the system router
  • Caches the current config; when config changes, cleans up the old subscription and creates a new one
  • Fetches the current value on each render to ensure freshness
  • Cleans up the subscription on node unmount

Integration#

The ConnectionVariableNode is registered in:
  • NodeRegistry as connectionVariable
  • NodeTypeSchema as 'connectionVariable'

Example Workflow Usage#

  1. Live Status: Read a mixer fader level variable and feed it into a LogicNode or DisplayNode
  2. Reactive Logic: Drive conditional behaviour based on a connection's current variable state
  3. Cross-Node Data: Pipe a connection variable into a MathNode or ExpressionNode for further processing

CounterNode#

The CounterNode maintains a persistent numeric counter that can be incremented, decremented, set, or reset through both state inputs and events.

Features#

  • Full Counter Operations: Increment by 1, decrement by 1, add an amount, subtract an amount, set to a value, or reset to the initial value
  • Event and State Support: Operations can be driven by both state inputs and event signals
  • Configurable Initial Value: Set the starting value for the counter and for resets
  • UI Actions: Supports direct increment/decrement/set actions from the editor UI

Usage#

initialValue: 0

increaseOne event → value: 1
increaseOne event → value: 2
decreaseOne event → value: 1
set input: 10 → value: 10
reset event → value: 0

Node Structure#

Config Schema#

  • initialValue (string | number, coerced to number, default: 0): Starting value and reset target

Input Schema#

  • set (string | number, optional): Set the counter to this value
  • reset (string | number | boolean, optional): Reset to initialValue when truthy
  • increaseOne (string | number | boolean, optional): Increment by 1 when truthy
  • increaseAmount (string | number, optional): Add this amount to the counter
  • decreaseOne (string | number | boolean, optional): Decrement by 1 when truthy
  • decreaseAmount (string | number, optional): Subtract this amount from the counter

Input Events#

  • increaseOne: Increment by 1
  • decreaseOne: Decrement by 1
  • increaseAmount: Add the event payload value
  • decreaseAmount: Subtract the event payload value
  • set: Set to the event payload value
  • reset: Reset to initialValue

Output Schema#

  • value (number): Current counter value

Output Events#

  • value: Emitted whenever the counter value changes

Implementation Details#

  • Tracks lastSeenInputs to detect state changes between renders
  • Operations from both state inputs (on change detection) and events are supported
  • The counter value is persisted in node state between renders

Integration#

The CounterNode is registered in:
  • NodeRegistry as counter
  • NodeTypeSchema as 'counter'

Example Workflow Usage#

  1. Tally Counter: Count button presses or event occurrences
  2. Loop Index: Use with an IntervalNode to increment a counter each tick and reset at a limit
  3. Score Tracker: Increment/decrement a score based on feedback events

DelayNode#

The DelayNode passes a payload value through after a configurable time delay. Multiple payloads can be in-flight simultaneously, each delayed by the same duration.

Features#

  • Configurable Delay: Set the delay in milliseconds (0 ms – 10 minutes)
  • Input Override: Delay duration can be overridden at runtime via the delay input
  • Buffered Payloads: Multiple events arriving in quick succession are each delayed independently
  • Timeout Management: Pending timeouts are cleared if the delay config changes

Usage#

delay: 1000ms, payload: "hello"

After 1 second → passthrough: "hello"
delay: 500ms, payloads arrive at t=0 and t=200ms

t=500: "first payload" emitted
t=700: "second payload" emitted

Node Structure#

Config Schema#

  • delay (number, min: 0, max: 600000, default: 1000): Delay in milliseconds

Input Schema#

  • delay (number, optional): Overrides config delay for this render
  • payload (unknown, optional): Value to delay

Input Events#

  • payload: Queues the carried value to be emitted after the delay

Output Schema#

  • passthrough (unknown): The payload value, emitted after the delay

Implementation Details#

  • Each incoming payload event schedules a setTimeout for the configured delay
  • When the delay config changes, all pending timeouts are cancelled and the array is cleared
  • Timeout handles are stored in an array and cleaned up on node unmount

Integration#

The DelayNode is registered in:
  • NodeRegistry as delay
  • NodeTypeSchema as 'delay'

Example Workflow Usage#

  1. Debounce: Add a short delay before an action to avoid triggering on transient signals
  2. Timed Sequence: Chain multiple DelayNodes to create a timed sequence of actions
  3. Hold Signal: Delay a feedback value by a fixed offset to synchronise it with another signal

DisplayNode#

The DisplayNode is a simple passthrough node for visualising a value inside the workflow editor. It caches and forwards whatever value it receives, making it useful for debugging and monitoring.

Features#

  • Value Visualisation: Displays the current value directly on the node in the editor canvas
  • Event Support: Responds to value events as well as state updates
  • Passthrough Output: Forwards the received value downstream unchanged
  • Configurable Label: The display label can be customised

Usage#

Connect any output to the value input. The current value is shown on the node and is also available as an output for further processing.

Node Structure#

Config Schema#

  • label (string, optional, default: 'Value'): Label shown on the node
  • enabled (boolean, default: true): Whether the node is active

Input Schema#

  • value (unknown): The value to display and pass through

Output Schema#

  • value (unknown): The input value, forwarded unchanged

Implementation Details#

  • Caches the most recent value in an internal property
  • Responds to value events via onEvent, updating the cache and re-rendering
  • Primarily intended for UI observability during workflow development

Integration#

The DisplayNode is registered in:
  • NodeRegistry as display
  • NodeTypeSchema as 'display'

Example Workflow Usage#

  1. Debug Monitor: Insert between two nodes to inspect intermediate values during development
  2. Status Display: Wire a connection variable to a DisplayNode to show its current value on the canvas

EventGateNode#

The EventGateNode is an event-driven gate that passes events through only when open, and blocks them when closed. It supports both state-based and event-based control modes.

Features#

  • Event Gating: Blocks or passes events based on gate state
  • Two Control Modes: Gate state can be driven by a continuous boolean input (state mode) or by discrete open/close/toggle events (event mode)
  • Configurable Initial State: The gate can start open or closed
  • Pass-through Output: Forwards the last allowed event payload as a state value

Usage#

State Mode#

Set controlMode to 'state' and connect a boolean to the open input. Events pass through whenever open is truthy.

Event Mode#

Set controlMode to 'event' and send open, close, or toggle events to control the gate. An event input event passes a payload through only if the gate is currently open.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • controlMode ('state' | 'event', default: 'event'): How the gate is controlled
  • initiallyOpen (boolean, default: true): Starting open/closed state

Input Schema#

  • open (boolean | string | number, optional): Gate control signal (state mode)

Output Schema#

  • value (unknown, optional): Last payload that passed through the gate
  • isOpen (boolean): Current open/closed state of the gate

Output Events#

  • out: Emitted when a payload passes through the gate

Input Events (event mode)#

  • open: Open the gate
  • close: Close the gate
  • toggle: Toggle the gate state
  • reset: Reset to the configured initial state
  • event: Pass a payload through (only if gate is open)

Implementation Details#

  • In event mode, gate state persists between renders
  • isOutputHandleEvent() returns true for the out handle
  • In state mode, gate state is derived directly from the open input each render

Integration#

The EventGateNode is registered in:
  • NodeRegistry as eventGate
  • NodeTypeSchema as 'eventGate'

Example Workflow Usage#

  1. Conditional Event Routing: Only allow trigger events through when a feedback state is active
  2. One-shot Gate: Open the gate via an event, let one payload through, then close it
  3. Arming Circuit: Open the gate only when a specific condition is met, preventing accidental action triggers

EventOrderNode#

The EventOrderNode validates that a set of events arrives in a specific sequential order. It emits a fulfilled event only when all events have been received in the correct sequence.

Features#

  • Ordered Sequence Validation: Tracks whether events arrive in the configured order (event1 → event2 → … → eventN)
  • Two Modes: Choose between ignoring out-of-order events (Wait) or resetting the sequence (Reset)
  • Configurable Sequence Length: Supports sequences of 2–20 events
  • Completion Event: Emits fulfilled when the full sequence is correctly completed

Usage#

Connect event sources to the numbered event inputs in order. Trigger event1 first, then event2, and so on. When the final event in the sequence arrives, the fulfilled event fires.
Sequence: event1 → event2 → event3

Correct: event1 ✓ → event2 ✓ → event3 ✓ → [fulfilled emitted]
Wrong (Reset mode): event1 ✓ → event3 ✗ → [reset, start over]
Wrong (Wait mode): event1 ✓ → event3 ✗ → [ignored, still waiting for event2]

Node Structure#

Config Schema#

  • mode ('Wait' | 'Reset', default: 'Reset'): Behaviour when an out-of-order event is received
  • numberOfInputs (number, min: 2, max: 20, default: 10): Length of the required sequence

Input Schema#

  • event1 … event10 (fixed set): Event inputs in sequence order

Output Schema#

  • state (boolean): Whether the full sequence has been completed
  • next (number): Index of the next expected event in the sequence

Implementation Details#

  • Maintains expectedEventIndex and currentState in node state
  • Wait mode: Out-of-order events are silently ignored
  • Reset mode: Out-of-order events reset expectedEventIndex to 0
  • On sequence completion, publishes the fulfilled event and resets for the next cycle

Integration#

The EventOrderNode is registered in:
  • NodeRegistry as eventOrder
  • NodeTypeSchema as 'eventOrder'

Example Workflow Usage#

  1. Combination Lock: Require a specific sequence of button presses before triggering an action
  2. Multi-step Handshake: Validate that a set of network or device events arrive in the correct protocol order
  3. Safety Interlock: Only allow an action when a required startup sequence has completed in order

EventSwitchNode#

The EventSwitchNode sets its output value by responding to named events. Each event is mapped to a specific value, making it easy to drive a downstream value from discrete event signals.

Features#

  • Event-Driven Value Selection: Each named event sets the output to its configured value
  • Configurable Event Map: Any number of events can be defined, each with a name and value
  • Reset Support: A reset event returns the output to the initial value
  • Persistent Value: The current value is stored and survives re-renders

Usage#

Define a set of events and their corresponding values in the config. When any of those events fires, the output value updates to the mapped value.
Events config:
- name: "on", value: true
- name: "off", value: false

Fire "on" → output: true
Fire "off" → output: false
Fire "reset" → output: <initialValue>

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true): Whether the node is active
  • initialValue (unknown, optional): Value to use before any event fires, and after a reset
  • events (array of {name, value}, default: []): The event-to-value mappings

Input Schema#

  • (no inputs)

Output Schema#

  • value (unknown): The current value as set by the most recent event

Input Events#

  • reset: Reset the output to initialValue
  • event_<name>: Set the output to the value mapped to <name>

Implementation Details#

  • Caches currentValue between renders
  • On onConfigChange, applies any change to initialValue
  • Event names in the config are prefixed with event_ internally

Integration#

The EventSwitchNode is registered in:
  • NodeRegistry as eventSwitch
  • NodeTypeSchema as 'eventSwitch'

Example Workflow Usage#

  1. State Machine: Drive a string output through a set of named states via events
  2. Scene Selector: Map scene-select button presses to scene name strings
  3. Mode Toggle: Cycle between operating modes by firing named events

ExpressionNode#

The ExpressionNode is a workflow node that evaluates expressions using the companion expression library. It mimics the LogicNode structure but provides more powerful expression evaluation capabilities with configurable inputs.

Features#

  • Expression Evaluation: Supports complex mathematical and logical expressions
  • Variable Injection: Can use variables from the workflow context
  • Configurable Inputs: Supports 1-20 dynamic input variables
  • Expression Mode: Uses the TextWithVariableInput component in expressionable mode
  • Error Handling: Provides clear error messages for invalid expressions

Usage#

Basic Expression#

_EXP_(1 + 2)
Result: 3

Using Dynamic Input Variables#

_EXP_($(var1) + $(var2))
With input variables: var1: 5, var2: 3
Result: 8

Using Variables and Dynamic Inputs#

_EXP_($(var1) > $(threshold) ? 'High' : 'Low')
With input variables: var1: 15, threshold: 10
Result: 'High'

String Interpolation#

Hello $(var1)!
With input variables: var1: 'World'
Result: Hello World!

Node Structure#

Input Schema#

  • expression (optional): The expression string to evaluate
  • variables (optional): Variables available to the expression
  • var1, var2, ..., varN (dynamic): Input variables based on numOfInputs configuration

Config Schema#

  • label (optional): Custom label for the node
  • enabled (default: true): Whether the node is enabled
  • numOfInputs (default: 1, min: 1, max: 20): Number of dynamic input variables
  • expression (default: '_EXP_()'): The default expression

Output Schema#

  • result: The evaluated result (can be any type)

Implementation Details#

The ExpressionNode uses the companion expression library:
  • ParseExpression: Parses the expression string into an AST
  • ResolveExpression: Evaluates the parsed expression with variables
  • ExpressionFunctions: Provides built-in functions for expressions
The node supports two modes:
  1. Expression Mode: When the input starts with _EXP_( and ends with )
  2. Variable Injection Mode: For simple string interpolation with $(variable) syntax

Integration#

The ExpressionNode is registered in:
  • NodeRegistry as expression
  • NodeTypeSchema as 'expression'

Example Workflow Usage#

  1. Simple Calculator: Set numOfInputs to 2, expression to _EXP_($(var1) + $(var2))
  2. Conditional Logic: Set numOfInputs to 3, expression to _EXP_($(var1) > $(var2) ? $(var3) : 'default')
  3. String Formatting: Set numOfInputs to 1, expression to Hello $(var1), the time is $(time.hh:mm:ss)!

FeedbackNode#

The FeedbackNode monitors the state of a feedback source on a connection and exposes it as a boolean output. It subscribes to live updates, so the output reflects the current state at all times.

Features#

  • Live Subscription: Automatically updates when the feedback state changes on the connection
  • Boolean Output: Normalises feedback state to true, false, or null
  • Dynamic Options: Feedback options are validated against the feedback definition's schema
  • Config-Driven Resubscription: Cleanly resubscribes when connection or feedback key changes

Usage#

Configure the connection ID, feedback key, and any required options. The state output will reflect the current boolean state of that feedback source.

Node Structure#

Config Schema#

  • connectionId (string): ID of the connection to monitor
  • feedbackKey (string): Key identifying the specific feedback to watch
  • options (record of string → string | number): Feedback-specific options

Input Schema#

  • (no inputs)

Output Schema#

  • state (boolean | null): Current state of the feedback (null if not yet received)

Implementation Details#

  • Subscribes to feedback state changes via the system router
  • Validates options against the feedback definition schema on each config change
  • Unsubscribes from the previous feedback before resubscribing when config changes
  • Cleans up all subscriptions on node unmount

Integration#

The FeedbackNode is registered in:
  • NodeRegistry as feedback
  • NodeTypeSchema as 'feedback'

Example Workflow Usage#

  1. Mute Indicator: Monitor an audio console mute feedback and drive a logic node based on its state
  2. Conditional Action: Wire state into a LogicNode to only execute an action when a specific feedback is active
  3. Display Status: Connect state to a DisplayNode to visualise a connection's current feedback state

InternalActionNode#

The InternalActionNode executes internal system actions — actions that are not tied to a specific device connection. It supports the same triggering modes as ActionNode.

Features#

  • Internal Actions: Targets the built-in system action registry rather than a connection
  • Flexible Triggering: Trigger on startup, data change, or incoming event
  • Dynamic Options: Action options are validated against the action's own schema
  • Input Overrides: Action key can be overridden from inputs

Usage#

Select an internal action key in the config and choose a trigger mode. Connect a trigger signal to the trigger input for event-driven execution.

Node Structure#

Config Schema#

  • actionKey (string, optional): ID of the internal action to execute
  • triggerOnEvent (boolean, optional): Fire when a trigger event is received
  • triggerOnChange (boolean, optional): Fire when inputs change
  • Additional action-specific option fields

Input Schema#

  • trigger (optional): Trigger signal — fires the action when an event arrives
  • actionKey (string, optional): Override the configured action key
  • Additional passthrough fields for action options

Output Schema#

  • (no outputs)

Implementation Details#

  • Uses the internalActions registry to resolve and validate the action
  • Executes via rpcClient.orchestrator.runInternalAction with a 5000ms timeout
  • Otherwise behaves identically to ActionNode

Integration#

The InternalActionNode is registered in:
  • NodeRegistry as internalAction
  • NodeTypeSchema as 'internalAction'

Example Workflow Usage#

  1. Page Navigation: Trigger an internal page-change action from a button press
  2. System Reset: Fire a system-level reset action on workflow startup

InternalFeedbackNode#

The InternalFeedbackNode monitors the state of an internal system feedback source (not tied to a device connection) and exposes its state as a boolean output.

Features#

  • Internal Feedback: Targets the built-in internal feedback registry
  • Live Subscription: Updates automatically when the feedback state changes
  • Boolean Output: Normalises feedback state to true, false, or null
  • Mapping Support: Decodes option mappings from JSON strings when needed

Usage#

Select an internal feedback key and configure any required options. The state output will reflect the current boolean state.

Node Structure#

Config Schema#

  • feedbackKey (string): ID of the internal feedback to monitor
  • options (record of string → string | number | boolean | array): Feedback-specific options

Input Schema#

  • (no inputs)

Output Schema#

  • state (boolean | null): Current state of the feedback

Implementation Details#

  • Uses the internalFeedbacks registry to resolve and validate the feedback
  • Decodes option values that are JSON strings (e.g. mappings stored as serialised arrays)
  • Cleans up subscriptions on node unmount

Integration#

The InternalFeedbackNode is registered in:
  • NodeRegistry as internalFeedback
  • NodeTypeSchema as 'internalFeedback'

Example Workflow Usage#

  1. Page State: Monitor which page is currently active and use the result to drive conditional logic
  2. System Status: Expose an internal system state as a boolean for downstream processing

IntervalNode#

The IntervalNode fires a trigger event repeatedly at a fixed interval, like a clock tick. It is useful for polling, periodic actions, and animation loops.

Features#

  • Periodic Triggering: Emits a trigger event at every configured interval
  • Configurable Rate: Set interval from 100ms to 10 minutes
  • Auto-Restart: Clears and restarts the interval whenever the config changes
  • Timestamp Output: Exposes the timestamp of the most recent tick

Usage#

Set the interval in milliseconds. The node will emit a trigger event and update timestamp on every tick.
interval: 1000ms → trigger event fires every second

Node Structure#

Config Schema#

  • interval (number, min: 100, max: 600000, default: 1000): Interval in milliseconds

Input Schema#

  • (no inputs)

Output Schema#

  • timestamp (number): Unix timestamp (ms) of the most recent tick

Output Events#

  • trigger: Emitted on every interval tick

Implementation Details#

  • Uses setInterval internally
  • Restarts the interval when the config changes to apply the new duration immediately
  • Calls workflow.rerenderFromNode() on each tick to propagate the updated timestamp
  • Cleans up the interval on node unmount

Integration#

The IntervalNode is registered in:
  • NodeRegistry as interval
  • NodeTypeSchema as 'interval'

Example Workflow Usage#

  1. Polling Loop: Trigger a feedback read or variable check every second
  2. Animation Tick: Drive an animation or counter update at a regular cadence
  3. Heartbeat: Send a periodic keep-alive action to a connected device

LogicNode#

The LogicNode evaluates a logical or comparison operation between two values and outputs a boolean result. It supports numeric comparisons, strict equality, and boolean logic operators.

Features#

  • Comparison Operators: ==, !=, >, <, >=, <=, ===, !==
  • Boolean Operators: AND, OR, XOR, NOT
  • Input and Config Values: Both values can be supplied via config (static) or inputs (dynamic)
  • Type Coercion: Numeric comparisons coerce string inputs to numbers

Usage#

Comparison#

valueA: 10, operator: ">", valueB: 5 → result: true
valueA: "on", operator: "==", valueB: "on" → result: true

Boolean Logic#

valueA: true, operator: "AND", valueB: false → result: false
valueA: true, operator: "NOT" → result: false

Node Structure#

Config Schema#

  • valueA (string | number | boolean, optional): Left-hand operand
  • operator (enum, optional): One of == != > < >= <= === !== AND OR XOR NOT
  • valueB (string | number | boolean, optional): Right-hand operand

Input Schema#

  • valueA (string | number | boolean, optional): Overrides config valueA
  • operator (enum, optional): Overrides config operator
  • valueB (string | number | boolean, optional): Overrides config valueB

Output Schema#

  • result (boolean): Result of the logical operation

Implementation Details#

  • Default operator is == when none is configured
  • NOT is a unary operator — only valueA is used
  • Numeric operators (>, <, >=, <=) cast both values to numbers before comparing
  • Input values take precedence over config values

Integration#

The LogicNode is registered in:
  • NodeRegistry as logic
  • NodeTypeSchema as 'logic'

Example Workflow Usage#

  1. Threshold Check: valueA = sensor reading, operator = >, valueB = threshold constant
  2. Gate Condition: Feed result into a StateGateNode or EventGateNode
  3. Inverter: Use NOT to invert a boolean feedback state

MathNode#

The MathNode performs a basic arithmetic operation on two numbers and outputs the result.

Features#

  • Four Arithmetic Operations: Addition, subtraction, multiplication, division
  • Type Coercion: String inputs are coerced to numbers automatically
  • Input and Config Values: Both operands can come from config (static) or inputs (dynamic)

Usage#

numberA: 10, operation: "add", numberB: 5 → result: 15
numberA: 10, operation: "subtract", numberB: 3 → result: 7
numberA: 4, operation: "multiply", numberB: 6 → result: 24
numberA: 20, operation: "divide", numberB: 4 → result: 5

Node Structure#

Config Schema#

  • numberA (string | number, coerced to number, optional): Left-hand operand
  • operation ('add' | 'subtract' | 'multiply' | 'divide', optional): Operation to perform
  • numberB (string | number, coerced to number, optional): Right-hand operand

Input Schema#

  • numberA (string | number, coerced to number, optional): Overrides config numberA
  • operation (enum, optional): Overrides config operation
  • numberB (string | number, coerced to number, optional): Overrides config numberB

Output Schema#

  • result (number): Result of the arithmetic operation

Implementation Details#

  • Default operation is add
  • Input values take precedence over config values
  • Division does not guard against divide-by-zero; the result will be Infinity or NaN

Integration#

The MathNode is registered in:
  • NodeRegistry as math
  • NodeTypeSchema as 'math'

Example Workflow Usage#

  1. Offset: Add a fixed offset to a sensor value before sending it downstream
  2. Scale: Multiply a normalised (0–1) value by 100 to get a percentage
  3. Counter Arithmetic: Combine with CounterNode to compute derived values

NFCNode#

The NFCNode listens for NFC card read events from a specific surface position (or all positions) and exposes the tag ID, surface, position, and timestamp.

Features#

  • NFC Event Subscription: Reacts to NFC card reads from physical surface positions
  • Position Filtering: Can listen to all positions or a specific position ID
  • Event Emission: Publishes an nfcRead event with the full read payload
  • Persistent Last Read: Stores the most recent read so state values are always current

Usage#

Leave positionId as null to receive reads from any position, or configure a specific position ID to filter to a single position.

Node Structure#

Config Schema#

  • positionId (string | null, default: null): Position to listen to, or null for all positions

Input Schema#

  • (no inputs)

Output Schema#

  • nfcId (string | null): ID of the NFC tag that was read
  • surfaceId (string | null): Surface where the tag was read
  • positionId (string | null): Position where the tag was read
  • timestamp (number | null): Timestamp of the read event

Output Events#

  • nfcRead: Emitted on each NFC read, carrying the full payload

Implementation Details#

  • Subscribes to position NFC events via the system router
  • Filters by positionId if one is configured
  • Calls workflow.rerenderFromNode() on each read to update downstream nodes
  • Cleans up the subscription on node unmount

Integration#

The NFCNode is registered in:
  • NodeRegistry as nfc
  • NodeTypeSchema as 'nfc'

Example Workflow Usage#

  1. Access Control: Trigger an action when a specific NFC tag is scanned at a position
  2. Asset Tracking: Log or display the ID of the last NFC tag read
  3. Multi-Position Monitor: Listen to all positions and route based on positionId output

OscListenerNode#

The OscListenerNode starts an OSC (Open Sound Control) UDP server and listens for incoming messages on configured paths. Each matched path emits a named event carrying the message parameters.

Features#

  • OSC Server: Hosts a UDP-based OSC listener on a configurable port
  • Path Matching: Supports exact paths, named params (:name), wildcards (*, **), and glob patterns
  • Named Endpoints: Each endpoint has a stable ID that becomes the event handle name
  • Parameter Extraction: Named route parameters are extracted and available as outputs
  • Legacy Path Support: Backwards-compatible with the older array-of-strings path format

Usage#

Configure endpoints with OSC paths. When a matching OSC message arrives, the corresponding event fires with the message parameters.
Endpoint: id="scene", path="/scene/:name"
Incoming: /scene/main → event "scene" fires, params.name = "main"

Endpoint: id="fader", path="/fader/*"
Incoming: /fader/1 → event "fader" fires

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • port (number, min: 1024, max: 65535): UDP port to listen on
  • endpoints (array of {id, path}, default: []): Named endpoint definitions
  • paths (array of string, default: []): Legacy path list (deprecated)

Input Schema#

  • Dynamic fields matching endpoint IDs (for state-based access)

Output Schema#

  • Dynamic fields for each endpoint: carries the last received parameters and payload
  • params (object): Named route parameters extracted from the path pattern

Output Events#

  • One event per endpoint ID, fired when a matching message is received

Implementation Details#

  • Starts an OSC UDP server on mount and restarts it on config changes
  • Path patterns are compiled to regex for efficient matching
  • Named params use :paramName syntax; wildcards use * (single segment) or ** (multi-segment)
  • Results are cached per endpoint ID so state values are always populated

Integration#

The OscListenerNode is registered in:
  • NodeRegistry as osc
  • NodeTypeSchema as 'osc'

Example Workflow Usage#

  1. Mixing Console: Listen for /channel/:num/fader messages and route them to connection actions
  2. Lighting Control: Receive OSC cues from a lighting console and trigger companion actions
  3. Multi-Parameter: Use named params to extract values directly from the OSC path

PriorityStackNode#

The PriorityStackNode selects a value from a set of inputs based on a configurable priority rule. When multiple inputs are active, the priority mode determines which one wins.

Features#

  • Multiple Priority Modes: top-to-bottom, bottom-to-top, last-changed, first-changed
  • Fallback Value: Returns a configurable fallback when no inputs are active
  • Active Input Tracking: Maintains a set of currently active inputs and their change timestamps
  • Ordered Output: Also exposes the full ordered list of active input IDs

Usage#

Add named inputs in the config. When those inputs receive truthy values, they are considered "active". The node selects the value of the highest-priority active input according to the chosen mode.
Inputs config: [A, B, C] (priority mode: topToBottom)
A = "hello" (truthy), B = false, C = "world" (truthy)

Result: "hello" (A has higher priority than C)

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • fallbackValue (unknown, optional): Value returned when no inputs are active
  • inputs (array of {id, label}, default: []): The named inputs to manage
  • priorityMode ('topToBottom' | 'bottomToTop' | 'lastChange' | 'firstChange', default: 'topToBottom'): How to select the winner

Input Schema#

  • Dynamic inputs matching the configured input IDs (boolean | string | number)

Output Schema#

  • value (unknown, optional): Value of the highest-priority active input, or fallbackValue
  • ordered (string[]): Ordered list of active input IDs from highest to lowest priority

Implementation Details#

  • An input is active if its value is truthy (non-zero, non-empty, non-false, non-null)
  • topToBottom / bottomToTop use the position of the input in the inputs config array
  • lastChange / firstChange use the timestamp of when each input last became active
  • Change timestamps are stored per input ID in lastChangeTs

Integration#

The PriorityStackNode is registered in:
  • NodeRegistry as priorityStack
  • NodeTypeSchema as 'priorityStack'

Example Workflow Usage#

  1. Layer Priority: Show the most recently activated overlay source
  2. Fallback Input: Select from a ranked list of video sources, showing the highest-priority active one
  3. Last-In-Wins: Use lastChange mode so the most recently activated input always wins

RestNode#

The RestNode hosts a Fastify HTTP server with configurable REST API endpoints. GET endpoints return current input values; POST endpoints emit events and cache received request bodies.

Features#

  • HTTP Server: Spins up a Fastify server on a configurable port
  • GET and POST Endpoints: GET returns live state data; POST captures body data and fires an event
  • Bearer Token Auth: Optional token-based authentication per request
  • Rate Limiting: Configurable request rate limits via @fastify/rate-limit
  • Named Endpoints: Each endpoint has a stable ID used as the event handle
  • Auto-Restart: Server restarts automatically on config changes

Usage#

GET Endpoint#

Configure a GET endpoint with path /status. The response will include the current value of the status input.

POST Endpoint#

Configure a POST endpoint with path /trigger. When a POST request arrives, a trigger event fires with the request body as its payload.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • port (number, min: 1024, max: 65535): HTTP port
  • rateLimit (optional): {max: number, timeWindow: number} — request rate limit
  • bearerTokens (array of {id, token}, default: []): Allowed bearer tokens
  • endpoints (array of {id, path, method}, default: []): Configured endpoints

Input Schema#

  • Dynamic fields matching GET endpoint IDs (data returned in GET responses)

Output Schema#

  • Dynamic fields matching POST endpoint IDs (last received body data)

Output Events#

  • One event per POST endpoint ID, fired on each request

Implementation Details#

  • Uses Fastify with @fastify/rate-limit plugin
  • Bearer token authentication checks the Authorization: Bearer <token> header
  • POST endpoints cache the request body and emit an event
  • GET endpoints return the current input value for that endpoint ID
  • Server is fully restarted on any config change

Integration#

The RestNode is registered in:
  • NodeRegistry as rest
  • NodeTypeSchema as 'rest'

Example Workflow Usage#

  1. Webhook Receiver: Receive webhook POSTs from external services and trigger workflow actions
  2. Status API: Expose current workflow state as a GET endpoint for external monitoring
  3. Remote Control: Trigger companion actions via HTTP requests from a control surface or script

SchedulerNode#

The SchedulerNode triggers on a cron schedule. It emits a trigger event and updates a timestamp output each time the cron expression fires.

Features#

  • Cron Scheduling: Uses standard cron expressions for flexible scheduling
  • Event Emission: Publishes a trigger event on each scheduled tick
  • Auto-Restart: Stops and restarts the cron task when the expression changes
  • Comprehensive Logging: Logs cron lifecycle events for debugging

Usage#

Set a valid cron expression in cronExpression. The node fires at each matching time.
cronExpression: "*/5 * * * *" → fires every 5 minutes
cronExpression: "0 9 * * 1-5" → fires at 9am on weekdays
cronExpression: "0 0 * * *" → fires at midnight every day

Node Structure#

Config Schema#

  • cronExpression (string): A valid cron expression

Input Schema#

  • (no inputs)

Output Schema#

  • timestamp (number): Unix timestamp (ms) of the most recent cron tick

Output Events#

  • trigger: Emitted on each cron tick

Implementation Details#

  • Uses the node-cron library
  • Manages a single ScheduledTask instance, replacing it when the expression changes
  • Logs scheduled, started, stopped, and destroyed lifecycle events
  • Cleans up the task on node unmount

Integration#

The SchedulerNode is registered in:
  • NodeRegistry as scheduler
  • NodeTypeSchema as 'scheduler'

Example Workflow Usage#

  1. Daily Report: Trigger a sequence of actions every morning at a specific time
  2. Business Hours: Fire events only during working hours using day-of-week and hour ranges
  3. Periodic Sync: Refresh connection state or send a sync command at regular intervals

StateGateNode#

The StateGateNode passes a payload value through to its output when the gate is open, and blocks it when closed. Unlike EventGateNode it operates on continuous state values rather than events.

Features#

  • State Gating: Passes payload through when open; returns fallback or cached value when closed
  • Two Control Modes: Gate state driven by a boolean input (state mode) or by discrete events (event mode)
  • Fallback Value: Optional fallback output when the gate is closed
  • Value Caching: Remembers the last payload seen while open

Usage#

State Mode#

Connect a boolean to the open input. While truthy, payload is forwarded to value. While falsy, value returns the fallback (or the last cached payload).

Event Mode#

Send open, close, or toggle events to control the gate. The payload input is the value being gated.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • controlMode ('state' | 'event', default: 'state'): How the gate is controlled
  • initiallyOpen (boolean, default: true): Starting state
  • open (boolean, optional): Static open state (used as config default in state mode)

Input Schema#

  • payload (unknown, optional): Value to gate
  • open (boolean | string | number, optional): Gate control signal (state mode)
  • fallback (unknown, optional): Value returned when gate is closed

Output Schema#

  • value (unknown, optional): Gated payload or fallback
  • isOpen (boolean): Current gate state

Input Events (event mode)#

  • open: Open the gate
  • close: Close the gate
  • toggle: Toggle the gate state
  • reset: Reset to initiallyOpen state

Implementation Details#

  • In state mode, gate state is computed from the open input on each render
  • In event mode, gate state persists and is modified by events
  • When closed: returns fallback if provided, otherwise returns the last cached payload value

Comparison with EventGateNode#

Feature
StateGateNode
EventGateNode
Gates continuous values
✓
✗
Gates events
✗
✓
State and event control modes
✓
✓

Integration#

The StateGateNode is registered in:
  • NodeRegistry as stateGate
  • NodeTypeSchema as 'stateGate'

Example Workflow Usage#

  1. Hold Last Value: Gate a sensor reading; when the gate closes, hold the last known value
  2. Conditional Display: Only pass a value to a display when a condition is met
  3. Safety Interlock: Block a value from reaching an ActionNode until an enable signal is asserted

StaticValueNode#

The StaticValueNode outputs a fixed, configured value of a chosen type. It is useful for injecting constants into a workflow.

Features#

  • Type Selection: Choose between string, number, or boolean output types
  • Type Coercion: The configured value is cast to the selected type at runtime
  • Enabled Toggle: When disabled, the node returns a safe default for the selected type

Usage#

type: "string", value: "hello" → result: "hello"
type: "number", value: "42" → result: 42
type: "boolean", value: true → result: true
Defaults when disabled:
  • string → ""
  • number → 0
  • boolean → false

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • type ('string' | 'number' | 'boolean', default: 'string'): Output type
  • value (string | number | boolean, default: ''): The static value to output

Input Schema#

  • (no inputs)

Output Schema#

  • result (string | number | boolean): The configured static value cast to the selected type

Implementation Details#

  • Type casting is done via a castValue method
  • When disabled, the type default is returned instead of the configured value

Integration#

The StaticValueNode is registered in:
  • NodeRegistry as staticValue
  • NodeTypeSchema as 'staticValue'

Example Workflow Usage#

  1. Constant Threshold: Provide a fixed number threshold to a LogicNode
  2. Label String: Inject a fixed string label into a StringMergeNode
  3. Feature Flag: Use a boolean constant to enable/disable a branch of logic

StringMergeNode#

The StringMergeNode concatenates multiple named input values into a single string, joined by a configurable separator.

Features#

  • Dynamic Inputs: Any number of named input variables can be defined
  • Configurable Separator: Choose any separator string (empty by default)
  • Null/Undefined Skipping: Missing or undefined inputs are omitted from the result

Usage#

separator: " ", var1: "Hello", var2: "World" → result: "Hello World"
separator: "-", var1: "2024", var2: "01", var3: "15" → result: "2024-01-15"
separator: "", var1: "foo", var2: undefined → result: "foo"

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • separator (string, default: ''): String placed between each value
  • inputVariables (array of {name, description}, default: []): Named inputs to merge

Input Schema#

  • Dynamic fields for each configured input variable name

Output Schema#

  • result (string): Concatenated string, or '' if disabled

Implementation Details#

  • Iterates over inputVariables in order, collecting non-null/undefined values
  • Joins with separator using Array.prototype.join
  • Returns '' when disabled

Integration#

The StringMergeNode is registered in:
  • NodeRegistry as stringMerge
  • NodeTypeSchema as 'stringMerge'

Example Workflow Usage#

  1. Date Formatter: Merge year, month, and day with - separator
  2. Message Builder: Combine a fixed prefix with a dynamic variable value
  3. CSV Row: Join multiple values with , to build a CSV line

TcpClientNode#

The TcpClientNode connects to a remote TCP server, sends messages, and receives data. It automatically reconnects on disconnect and supports delimiter-based message framing.

Features#

  • Auto-Reconnect: Reconnects automatically at a configurable interval after disconnection
  • Idle Disconnect: Optionally disconnects after a period of inactivity
  • Delimiter Framing: Buffer incoming data until a delimiter (LF, CRLF, CR, null byte) before emitting
  • JSON Parsing: Attempts to JSON-parse each received message and exposes the result
  • Connection Events: Optionally emits a connection event on (re)connect
  • Send on Change: Sends the send_state value whenever it changes

Usage#

Configure the host and port. Wire a string to send_state to send it whenever the value changes. Incoming messages appear on lastMessage and lastObject.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • host (string, min length: 1): Remote hostname or IP address
  • port (number, min: 1, max: 65535): Remote port
  • reconnectInterval (number, default: 5000): Reconnect delay in ms
  • disconnectWhenIdle (boolean, default: false): Disconnect after idle period
  • idleDisconnectDelay ('0' | '200' | '1000' | '10000' | '60000', default: '1000'): Idle timeout in ms
  • emitOnConnect (boolean, default: false): Emit connection event on connect
  • delimiter ('none' | 'null' | 'lf' | 'crlf' | 'cr', default: 'none'): Message delimiter
  • bufferUntilDelimiter (boolean, default: false): Buffer data until delimiter is found
  • maxBufferSize (number, default: 65536): Max buffer size before truncation

Input Schema#

  • send_state (string, optional): Message to send to the remote server

Output Schema#

  • isConnected (boolean): Whether the TCP connection is active
  • lastMessage (string): Most recently received message
  • lastObject (unknown): JSON-parsed version of the last message (if parseable)

Output Events#

  • message: Emitted on each received message
  • connection: Emitted on connect (if emitOnConnect is enabled)

Integration#

The TcpClientNode is registered in:
  • NodeRegistry as tcpClient
  • NodeTypeSchema as 'tcpClient'

Example Workflow Usage#

  1. Device Control: Send commands to a device over TCP and process its responses
  2. Telnet-Style Interface: Connect to a text-based TCP service and parse responses
  3. Raw Protocol: Use no delimiter for binary/streaming protocols

TcpServerNode#

The TcpServerNode listens for incoming TCP connections, broadcasts messages to all connected clients, and exposes data received from any client.

Features#

  • Multi-Client Support: Accepts and manages multiple simultaneous TCP connections
  • Broadcast: Sends the send_state value to all currently connected clients
  • Delimiter Framing: Per-client message buffering with configurable delimiters
  • JSON Parsing: Attempts to parse received messages as JSON
  • Client Tracking: Exposes connection count, last sender IP/port, and last received message
  • Error Reporting: Surfaces server errors via the errorMessage output

Usage#

Configure a port to listen on. Wire a string to send_state to broadcast it to all clients. Incoming messages from any client appear on the lastMessage and related outputs.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • port (number, min: 1024, max: 65535): TCP port to listen on
  • delimiter ('none' | 'null' | 'lf' | 'crlf' | 'cr', default: 'none'): Message delimiter
  • bufferUntilDelimiter (boolean, default: false): Buffer per-client data until delimiter
  • maxBufferSize (number, default: 65536): Max per-client buffer size

Input Schema#

  • send_state (string, optional): Message to broadcast to all connected clients

Output Schema#

  • isConnected (boolean): Whether at least one client is connected
  • connectionCount (number): Number of currently connected clients
  • lastMessage (string): Most recently received message (from any client)
  • lastObject (unknown): JSON-parsed version of the last message
  • lastTimestamp (number): Timestamp of the last received message
  • lastFromIp (string): IP address of the last sender
  • lastFromPort (number): Port of the last sender
  • errorMessage (string): Last server error message

Integration#

The TcpServerNode is registered in:
  • NodeRegistry as tcpServer
  • NodeTypeSchema as 'tcpServer'

Example Workflow Usage#

  1. Control Surface Server: Accept connections from multiple control surfaces and broadcast state
  2. Data Aggregator: Collect incoming data from multiple TCP clients and process it centrally
  3. Echo Server: Receive messages and send responses back to all clients

UdpReceiverNode#

The UdpReceiverNode binds a UDP socket on a configured port and receives datagrams from any sender. It supports delimiter-based message buffering and exposes sender metadata alongside the received data.

Features#

  • UDP Listener: Binds a UDP socket and receives datagrams from multiple senders
  • Per-Sender Buffering: Message buffering tracked per source address
  • Delimiter Framing: Buffer data until a delimiter before treating it as a complete message
  • JSON Parsing: Attempts to parse each message as JSON
  • Sender Metadata: Exposes the IP address and port of the last sender
  • Event Emission: Emits a message event on each received message

Usage#

Configure the port. Incoming UDP datagrams are available on lastMessage and lastObject. The message event fires on each datagram.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • port (number, min: 1024, max: 65535): UDP port to bind on
  • delimiter ('none' | 'null' | 'lf' | 'crlf' | 'cr', default: 'none'): Message delimiter
  • bufferUntilDelimiter (boolean, default: false): Buffer per-sender data until delimiter
  • maxBufferSize (number, default: 65536): Max buffer size per sender

Input Schema#

  • (no inputs)

Output Schema#

  • lastMessage (string): Most recently received message
  • lastObject (unknown): JSON-parsed version of the last message
  • lastAddress (string): IP address of the last sender
  • lastPort (number): Port of the last sender
  • lastTimestamp (number): Timestamp of the last received message
  • errorMessage (string): Last socket error message

Output Events#

  • message: Emitted on each received datagram

Integration#

The UdpReceiverNode is registered in:
  • NodeRegistry as udpReceiver
  • NodeTypeSchema as 'udpReceiver'

Example Workflow Usage#

  1. OSC Alternative: Receive raw UDP messages from devices that don't support OSC framing
  2. Sensor Data: Ingest UDP telemetry from sensors or embedded devices
  3. Broadcast Receiver: Listen for UDP broadcast packets on the local network

UdpSenderNode#

The UdpSenderNode sends UDP datagrams to a configured host and port. The destination can be overridden at runtime via input values.

Features#

  • UDP Sending: Sends datagrams to a configured or dynamically specified host/port
  • Input Overrides: Host and port can be overridden per-render via host_input and port_input
  • Message Delimiter: Optionally appends a delimiter to each outgoing message
  • Local Port Binding: Can bind to a specific local port, or use 0 for auto-assignment
  • Send Confirmation: Emits a sent event and updates last-sent metadata after each send

Usage#

Configure the default host and port. Wire a string to send_state to send it. Override the destination dynamically using host_input and port_input.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • host (string, optional): Default destination hostname or IP
  • port (number, optional): Default destination port
  • localPort (number, optional): Local port to bind (0 = auto)
  • delimiter ('none' | 'null' | 'lf' | 'crlf' | 'cr', default: 'none'): Appended delimiter

Input Schema#

  • send_state (string, optional): Message to send
  • host_input (string, optional): Overrides config host
  • port_input (number, optional): Overrides config port

Output Schema#

  • lastSentMessage (string): Last message that was sent
  • lastSentAddress (string): Destination address of the last send
  • lastSentPort (number): Destination port of the last send
  • errorMessage (string): Last send error message

Output Events#

  • sent: Emitted after each successful send

Integration#

The UdpSenderNode is registered in:
  • NodeRegistry as udpSender
  • NodeTypeSchema as 'udpSender'

Example Workflow Usage#

  1. Device Command: Send UDP control commands to a device that accepts UDP input
  2. Dynamic Routing: Use host_input and port_input to route messages to different destinations based on workflow state
  3. Broadcast: Send to the subnet broadcast address to reach all devices on the local network

WebSocketClientNode#

The WebSocketClientNode connects to a remote WebSocket server, sends messages, and receives data. It automatically reconnects on disconnect and supports idle-based disconnection.

Features#

  • Auto-Reconnect: Reconnects automatically at a configurable interval
  • Idle Disconnect: Optionally disconnects after a period without outgoing messages
  • JSON Parsing: Attempts to parse each received message as JSON
  • Connection Events: Optionally emits a connection event on (re)connect
  • Send on Change: Sends the send_state value whenever it changes

Usage#

Configure the WebSocket url. Wire a string to send_state to send messages. Received messages appear on lastMessage and lastObject.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • url (string, min length: 1): WebSocket URL to connect to (e.g. ws://host:port/path)
  • reconnectInterval (number, default: 5000): Reconnect delay in ms
  • disconnectWhenIdle (boolean, default: false): Disconnect after idle period
  • idleDisconnectDelay ('0' | '200' | '1000' | '10000' | '60000', default: '1000'): Idle timeout in ms
  • emitOnConnect (boolean, default: false): Emit connection event on connect

Input Schema#

  • send_state (string, optional): Message to send to the server

Output Schema#

  • isConnected (boolean): Whether the WebSocket is currently connected
  • lastMessage (string): Most recently received message
  • lastObject (unknown): JSON-parsed version of the last message

Output Events#

  • message: Emitted on each received message
  • connection: Emitted on connect (if emitOnConnect is enabled)

Integration#

The WebSocketClientNode is registered in:
  • NodeRegistry as webSocketClient
  • NodeTypeSchema as 'webSocketClient'

Example Workflow Usage#

  1. API Integration: Connect to a WebSocket API and react to incoming messages
  2. Real-Time Data: Subscribe to a live data feed and pass values downstream
  3. Bidirectional Control: Send commands and receive state updates over a single WebSocket connection

WebSocketServerNode#

The WebSocketServerNode hosts a WebSocket server that accepts client connections, broadcasts messages to all connected clients, and exposes data received from any client.

Features#

  • Multi-Client Support: Accepts and manages multiple simultaneous WebSocket connections
  • Broadcast: Sends the send_state value to all connected clients
  • Client ID Tracking: Each connecting client receives an auto-incremented ID
  • JSON Parsing: Attempts to parse received messages as JSON
  • Connection Events: Optionally emits a connection event when a new client connects
  • Error Reporting: Surfaces server errors via the errorMessage output

Usage#

Configure a port. Clients connect via ws://host:port. Wire a string to send_state to broadcast it. Incoming messages appear on lastMessage and related outputs.

Node Structure#

Config Schema#

  • label (string, optional): Node label
  • enabled (boolean, default: true)
  • port (number, min: 1024, max: 65535): WebSocket port to listen on
  • emitOnConnect (boolean, default: false): Emit connection event when a client connects

Input Schema#

  • send_state (string, optional): Message to broadcast to all connected clients

Output Schema#

  • isConnected (boolean): Whether at least one client is connected
  • connectionCount (number): Number of currently connected clients
  • lastMessage (string): Most recently received message (from any client)
  • lastObject (unknown): JSON-parsed version of the last message
  • lastTimestamp (number): Timestamp of the last received message
  • lastFromId (string): Client ID of the last sender
  • errorMessage (string): Last server error message

Output Events#

  • connection: Emitted when a client connects (if emitOnConnect is enabled)

Integration#

The WebSocketServerNode is registered in:
  • NodeRegistry as webSocketServer
  • NodeTypeSchema as 'webSocketServer'

Example Workflow Usage#

  1. Browser Dashboard: Serve real-time state to a web dashboard connected via WebSocket
  2. Control Protocol: Accept commands from custom WebSocket clients and trigger workflow actions
  3. State Broadcast: Push workflow state updates to all listening clients whenever values change

WorkflowRouterNode#

The WorkflowRouterNode is a dynamic signal router that maps configurable sources to destinations across one or more levels. Routes are persisted to the database and survive restarts.

Features#

  • Dynamic Routing: Connects any source to any destination at runtime
  • Multi-Level: Supports up to 10 independent routing levels (e.g. for video, audio, data)
  • Scalable: Up to 1000 sources and 1000 destinations per router
  • Persistent Routes: Routes are saved to the database with a 5-second debounce
  • Cross-Workflow Validation: Validates that source and destination nodes belong to the same workflow
  • Dynamic I/O: Source and destination counts can be changed without losing existing routes

Usage#

Configure the number of sources, destinations, and levels. Use the editor UI to assign routes. The output_<dest> values reflect the current value of whatever source is routed to each destination. An unrouted_<dest> value appears when no source is assigned.

Node Structure#

Config Schema#

  • label (string, default: 'Router'): Node label
  • sourceCount (number, min: 1, max: 1000, default: 10): Number of source inputs
  • destinationCount (number, min: 1, max: 1000, default: 10): Number of destination outputs
  • levels (number, min: 1, max: 10, default: 1): Number of independent routing levels

Input Schema#

  • Dynamic inputs for each source (boolean | string | number | null)

Output Schema#

  • output_<N> for each destination: Current value of the routed source, or fallback if unrouted
  • unrouted_<N> (boolean): Whether destination N is currently unrouted
  • ordered (array): Ordered list of active source IDs by destination

Implementation Details#

  • Built with the Effect library for typed error handling and resource management
  • Routes are stored in the database with a 5-second write debounce to reduce I/O
  • In-memory cache is the source of truth; the database is used only for persistence and initial load
  • Orphaned ports (from reduced source/destination counts) are cleaned up on config change
  • Cross-workflow routing is blocked with a validation error

Integration#

The WorkflowRouterNode is registered in:
  • NodeRegistry as workflowRouter
  • NodeTypeSchema as 'workflowRouter'

Example Workflow Usage#

  1. Video Router: Route camera feeds to output destinations with a visual matrix UI
  2. Audio Routing: Assign audio sources to mix bus destinations across multiple levels
  3. Signal Matrix: General-purpose N×M routing matrix for any type of signal value

WorkflowVariableNode#

The WorkflowVariableNode stores a typed value scoped to the current workflow. It acts as a shared memory cell: other nodes can write to it and read from it. Values can optionally be persisted to the database.

Features#

  • Typed Storage: Stores a string, number, or boolean value with type enforcement
  • Read and Write: Exposes both a write input and a read output on the same node
  • Optional Persistence: Can save the value to the database so it survives restarts
  • Live Sync: Broadcasts changes via Redis so all nodes reacting to this variable update immediately
  • Controlled/Uncontrolled Modes: When write is connected, the node is controlled by that input; when disconnected, it manages its own state

Usage#

Connect a value to write to update the variable. Read the current value from the read output. Other nodes in the same workflow can reference this variable by its variableKey.

Node Structure#

Config Schema#

  • schema ({type: 'string' | 'number' | 'boolean'}): The type of the variable
  • initialValue (unknown): Value used on first creation
  • variableKey (string): Unique identifier for this variable within the workflow
  • persist (boolean, default: false): Whether to persist the value to the database

Input Schema#

  • write (string | number | boolean | object | null, optional): Value to write to the variable

Output Schema#

  • read (string | number | boolean | object | null, optional): Current value of the variable

Implementation Details#

  • Initialises from Redis, the persisted database value, or initialValue (in that priority order)
  • Persistence is throttled to a maximum of once every 30 seconds
  • Type casting produces a friendly error message if the written value cannot be cast to the configured type
  • Cross-node reactivity via Redis pub/sub

Integration#

The WorkflowVariableNode is registered in:
  • NodeRegistry as workflowVariable
  • NodeTypeSchema as 'workflowVariable'

Example Workflow Usage#

  1. Shared State: Store a mode value that multiple branches of the workflow read
  2. Persisted Counter: Track a count that survives workflow restarts
  3. Cross-Node Communication: Write from one part of the workflow and read in another without direct connections

WorkflowVariableReadNode#

The WorkflowVariableReadNode reads the current value of a variable from another workflow. It subscribes to live updates so the output always reflects the latest value.

Features#

  • Cross-Workflow Read: Accesses variables defined in a different workflow
  • Live Subscription: Automatically updates when the target variable changes
  • Schema Validation: Validates the received value against the target variable's type schema
  • Reactive: Triggers a re-render when the value changes

Usage#

Configure the workflowId of the workflow that owns the variable, and the variableKey of the variable to read. The read output reflects its current value.

Node Structure#

Config Schema#

  • workflowId (string): ID of the workflow that owns the variable
  • variableKey (string): Key of the variable to read

Input Schema#

  • (no inputs)

Output Schema#

  • read (string | number | boolean | object | null, optional): Current value of the variable

Implementation Details#

  • Subscribes to variable change notifications for the target workflow/key pair
  • Validates the incoming value against the target variable's type schema
  • Cleans up the subscription on node unmount or config change

Comparison with WorkflowVariableNode#

Feature
WorkflowVariableNode
WorkflowVariableReadNode
Same-workflow variable
✓
✗
Cross-workflow read
✗
✓
Write support
✓
✗

Integration#

The WorkflowVariableReadNode is registered in:
  • NodeRegistry as workflowVariableRead
  • NodeTypeSchema as 'workflowVariableRead'

Example Workflow Usage#

  1. Global Config: Read a configuration value maintained in a dedicated "globals" workflow
  2. Shared Counter: Display or use a counter that is owned and managed by another workflow
  3. Cross-Workflow Sync: Synchronise state between two workflows without direct connections

WorkflowVariableWriteNode#

The WorkflowVariableWriteNode writes a value to a variable defined in another workflow. It validates the written value against the target variable's type schema before writing.

Features#

  • Cross-Workflow Write: Updates a variable in a different workflow
  • Type Validation: Strictly validates the value against the target variable's schema (no coercion)
  • Reactive: Re-validates and writes whenever the write input changes

Usage#

Configure the workflowId of the target workflow and the variableKey. Connect the value to write to the write input. The value will be written to the target variable whenever it changes.

Node Structure#

Config Schema#

  • workflowId (string): ID of the workflow that owns the variable
  • variableKey (string): Key of the variable to write to

Input Schema#

  • write (string | number | boolean | object | null, optional): Value to write

Output Schema#

  • (no outputs)

Implementation Details#

  • Validates the value against the target variable's type schema before writing
  • Uses strict type validation — values are not coerced to the target type
  • Subscribes to the target schema to stay up to date with type changes
  • Cleans up subscriptions on node unmount

Comparison with WorkflowVariableNode#

Feature
WorkflowVariableNode
WorkflowVariableWriteNode
Same-workflow variable
✓
✗
Cross-workflow write
✗
✓
Read support
✓
✗

Integration#

The WorkflowVariableWriteNode is registered in:
  • NodeRegistry as workflowVariableWrite
  • NodeTypeSchema as 'workflowVariableWrite'

Example Workflow Usage#

  1. Remote Update: Write a computed value from one workflow into a variable owned by another
  2. Coordinator Pattern: Have a "controller" workflow update shared variables consumed by multiple "view" workflows

Was this helpful?

Was this helpful?

0 of 0 users found this page helpful