Actions

Complete reference for action definitions and step types

Overview

Actions define how your application responds to user interactions and events. Each action consists of a name and a sequence of steps that execute in order.

Action Definition

json
{
  "name": "incrementCounter",
  "steps": [
    { "do": "update", "target": "count", "operation": "increment" }
  ]
}
NameTypeRequiredDefaultDescription
namestringYes-Unique identifier for the action. Used in event handlers.
stepsActionStep[]Yes-Array of steps to execute when the action is triggered.

Set Step

Directly sets a state value.

json
{
  "do": "set",
  "target": "message",
  "value": { "expr": "lit", "value": "Hello!" }
}
NameTypeRequiredDefaultDescription
do"set"Yes-Step type identifier.
targetstringYes-State field to modify. Use dot notation for nested paths.
valueExpressionYes-Expression that evaluates to the new value.

Examples

json
// Set a simple value
{ "do": "set", "target": "name", "value": { "expr": "lit", "value": "John" } }

// Set from event parameter
{
  "do": "set",
  "target": "inputValue",
  "value": { "expr": "param", "name": "event", "path": "target.value" }
}

// Set nested property
{
  "do": "set",
  "target": "user.profile.name",
  "value": { "expr": "lit", "value": "Jane" }
}

Update Step

Applies a predefined operation to a state value.

json
{
  "do": "update",
  "target": "count",
  "operation": "increment"
}
NameTypeRequiredDefaultDescription
do"update"Yes-Step type identifier.
targetstringYes-State field to modify.
operationstringYes-Operation to perform (see operations table).
valueExpressionNo-Value for operations that need one (e.g., push, remove).

Operations

OperationDescriptionRequires ValueState Type
incrementAdds to a number (default: 1)No (optional value)number
decrementSubtracts from a number (default: 1)No (optional value)number
toggleFlips a boolean valueNoboolean
pushAppends to an arrayYeslist
popRemoves last element from arrayNolist
removeRemoves matching element from arrayYeslist
replaceAtReplaces element at a specific indexYes (index + value)list
insertAtInserts element at a specific indexYes (index + value)list
spliceDeletes and/or inserts at indexYes (index + deleteCount, optional value)list
mergeShallow-merges properties into an objectYesobject

Examples

json
// Increment counter
{ "do": "update", "target": "count", "operation": "increment" }

// Add item to array
{
  "do": "update",
  "target": "todos",
  "operation": "push",
  "value": { "expr": "state", "name": "newTodo" }
}

// Remove item from array
{
  "do": "update",
  "target": "items",
  "operation": "remove",
  "value": { "expr": "var", "name": "itemToRemove" }
}

// Remove last item
{ "do": "update", "target": "stack", "operation": "pop" }

toggle

Flips a boolean state value. Ideal for toggles, modals, and visibility controls.

json
{ "do": "update", "target": "isOpen", "operation": "toggle" }
NameTypeRequiredDefaultDescription
do"update"Yes-Step type identifier.
targetstringYes-State field to toggle (must be boolean).
operation"toggle"Yes-Toggle operation identifier.

merge

Shallow-merges properties into an object state. Existing properties are preserved unless overwritten.

json
{
  "do": "update",
  "target": "form",
  "operation": "merge",
  "value": { "expr": "lit", "value": { "email": "user@example.com" } }
}
NameTypeRequiredDefaultDescription
do"update"Yes-Step type identifier.
targetstringYes-State field to merge into (must be object).
operation"merge"Yes-Merge operation identifier.
valueExpressionYes-Object expression to merge into target.

Merge Example

json
// State: form = { name: "John", email: "" }
{
  "do": "update",
  "target": "form",
  "operation": "merge",
  "value": { "expr": "lit", "value": { "email": "john@example.com", "phone": "123-456" } }
}
// Result: form = { name: "John", email: "john@example.com", phone: "123-456" }

replaceAt

Replaces an element at a specific index in an array. Useful for editing list items in place.

json
{
  "do": "update",
  "target": "todos",
  "operation": "replaceAt",
  "index": { "expr": "var", "name": "index" },
  "value": { "expr": "lit", "value": { "title": "Updated", "done": true } }
}
NameTypeRequiredDefaultDescription
do"update"Yes-Step type identifier.
targetstringYes-State field (must be list).
operation"replaceAt"Yes-ReplaceAt operation identifier.
indexExpressionYes-Expression evaluating to the index to replace.
valueExpressionYes-Expression evaluating to the new value.

insertAt

Inserts an element at a specific index in an array. Elements at and after the index are shifted.

json
{
  "do": "update",
  "target": "items",
  "operation": "insertAt",
  "index": { "expr": "lit", "value": 0 },
  "value": { "expr": "state", "name": "newItem" }
}
NameTypeRequiredDefaultDescription
do"update"Yes-Step type identifier.
targetstringYes-State field (must be list).
operation"insertAt"Yes-InsertAt operation identifier.
indexExpressionYes-Expression evaluating to the index to insert at.
valueExpressionYes-Expression evaluating to the value to insert.

splice

Deletes and/or inserts items at a specific index. The most flexible list operation, mirroring JavaScript's Array.prototype.splice().

json
{
  "do": "update",
  "target": "items",
  "operation": "splice",
  "index": { "expr": "var", "name": "index" },
  "deleteCount": { "expr": "lit", "value": 1 },
  "value": { "expr": "lit", "value": ["replacement1", "replacement2"] }
}
NameTypeRequiredDefaultDescription
do"update"Yes-Step type identifier.
targetstringYes-State field (must be list).
operation"splice"Yes-Splice operation identifier.
indexExpressionYes-Expression evaluating to the start index.
deleteCountExpressionYes-Expression evaluating to the number of elements to delete.
valueExpressionNo-Expression evaluating to an array of items to insert (optional).

Fetch Step

Makes an HTTP request and handles the response.

json
{
  "do": "fetch",
  "url": { "expr": "lit", "value": "https://api.example.com/data" },
  "method": "GET",
  "result": "fetchedData",
  "onSuccess": [
    { "do": "set", "target": "isLoading", "value": { "expr": "lit", "value": false } }
  ],
  "onError": [
    { "do": "set", "target": "error", "value": { "expr": "param", "name": "error" } }
  ]
}
NameTypeRequiredDefaultDescription
do"fetch"Yes-Step type identifier.
urlExpressionYes-Expression that evaluates to the request URL.
method"GET" | "POST" | "PUT" | "DELETE"No"GET"HTTP method.
bodyExpressionNo-Request body (for POST, PUT). Will be JSON stringified.
resultstringNo-State field to store the response data.
onSuccessActionStep[]No-Steps to execute on successful response.
onErrorActionStep[]No-Steps to execute on error.

HTTP Methods

MethodDescriptionTypical Use
GETRetrieve dataFetching lists, details
POSTCreate new resourceSubmitting forms, creating items
PUTUpdate existing resourceEditing items
DELETERemove resourceDeleting items

Complete Fetch Example

json
{
  "name": "loadUsers",
  "steps": [
    {
      "do": "set",
      "target": "isLoading",
      "value": { "expr": "lit", "value": true }
    },
    {
      "do": "fetch",
      "url": { "expr": "lit", "value": "https://api.example.com/users" },
      "method": "GET",
      "result": "users",
      "onSuccess": [
        {
          "do": "set",
          "target": "isLoading",
          "value": { "expr": "lit", "value": false }
        }
      ],
      "onError": [
        {
          "do": "set",
          "target": "isLoading",
          "value": { "expr": "lit", "value": false }
        },
        {
          "do": "set",
          "target": "errorMessage",
          "value": { "expr": "lit", "value": "Failed to load users" }
        }
      ]
    }
  ]
}

POST Request Example

json
{
  "name": "createTodo",
  "steps": [
    {
      "do": "fetch",
      "url": { "expr": "lit", "value": "https://api.example.com/todos" },
      "method": "POST",
      "body": {
        "expr": "state",
        "name": "newTodo"
      },
      "onSuccess": [
        {
          "do": "update",
          "target": "todos",
          "operation": "push",
          "value": { "expr": "param", "name": "result" }
        },
        {
          "do": "set",
          "target": "newTodo",
          "value": { "expr": "lit", "value": { "title": "", "completed": false } }
        }
      ]
    }
  ]
}

Combining Steps

Actions can contain multiple steps that execute sequentially:

json
{
  "name": "submitForm",
  "steps": [
    {
      "do": "set",
      "target": "isSubmitting",
      "value": { "expr": "lit", "value": true }
    },
    {
      "do": "set",
      "target": "error",
      "value": { "expr": "lit", "value": null }
    },
    {
      "do": "fetch",
      "url": { "expr": "lit", "value": "/api/submit" },
      "method": "POST",
      "body": { "expr": "state", "name": "formData" },
      "onSuccess": [
        {
          "do": "set",
          "target": "isSubmitting",
          "value": { "expr": "lit", "value": false }
        },
        {
          "do": "set",
          "target": "submitted",
          "value": { "expr": "lit", "value": true }
        }
      ],
      "onError": [
        {
          "do": "set",
          "target": "isSubmitting",
          "value": { "expr": "lit", "value": false }
        },
        {
          "do": "set",
          "target": "error",
          "value": { "expr": "param", "name": "error" }
        }
      ]
    }
  ]
}

Navigate Step

Navigates to a different URL or page.

json
{
  "do": "navigate",
  "url": { "expr": "lit", "value": "/dashboard" }
}
NameTypeRequiredDefaultDescription
do"navigate"Yes-Step type identifier.
urlExpressionYes-Expression that evaluates to the target URL.
target"_self" | "_blank"No"_self"Navigation target (same tab or new tab).
replacebooleanNofalseUse history.replaceState instead of pushState.

Examples

json
// Navigate to a page
{ "do": "navigate", "url": { "expr": "lit", "value": "/about" } }

// Open in new tab
{
  "do": "navigate",
  "url": { "expr": "lit", "value": "https://example.com" },
  "target": "_blank"
}

// Dynamic navigation
{
  "do": "navigate",
  "url": {
    "expr": "bin",
    "op": "+",
    "left": { "expr": "lit", "value": "/posts/" },
    "right": { "expr": "var", "name": "postId" }
  }
}

Storage Step

Interacts with browser localStorage or sessionStorage.

json
{
  "do": "storage",
  "operation": "get",
  "key": { "expr": "lit", "value": "theme" },
  "storage": "local",
  "result": "savedTheme"
}
NameTypeRequiredDefaultDescription
do"storage"Yes-Step type identifier.
operation"get" | "set" | "remove"Yes-Storage operation to perform.
keyExpressionYes-Expression that evaluates to the storage key.
storage"local" | "session"Yes-Storage type (localStorage or sessionStorage).
valueExpressionNo-Value to store (required for 'set' operation).
resultstringNo-Variable name to store the retrieved value (for 'get' operation).
onSuccessActionStep[]No-Steps to execute on success.
onErrorActionStep[]No-Steps to execute on error.

Storage Operations

OperationDescriptionRequires ValueRequires Result
getRetrieve value from storageNoYes (recommended)
setStore value in storageYesNo
removeRemove key from storageNoNo

Examples

json
// Save theme preference
{
  "do": "storage",
  "operation": "set",
  "key": { "expr": "lit", "value": "theme" },
  "value": { "expr": "state", "name": "theme" },
  "storage": "local"
}

// Load theme on mount
{
  "do": "storage",
  "operation": "get",
  "key": { "expr": "lit", "value": "theme" },
  "storage": "local",
  "result": "savedTheme",
  "onSuccess": [
    {
      "do": "if",
      "condition": { "expr": "var", "name": "savedTheme" },
      "then": [
        { "do": "set", "target": "theme", "value": { "expr": "var", "name": "savedTheme" } }
      ]
    }
  ]
}

// Clear user session
{
  "do": "storage",
  "operation": "remove",
  "key": { "expr": "lit", "value": "userToken" },
  "storage": "session"
}

DOM Step

Performs direct DOM manipulation operations.

json
{
  "do": "dom",
  "operation": "addClass",
  "selector": { "expr": "lit", "value": "html" },
  "value": { "expr": "lit", "value": "dark" }
}
NameTypeRequiredDefaultDescription
do"dom"Yes-Step type identifier.
operationstringYes-DOM operation to perform (see operations table).
selectorExpressionYes-CSS selector or 'html'/'body' for document elements.
valueExpressionNo-Class name or attribute value.
attributestringNo-Attribute name (for setAttribute/removeAttribute).

DOM Operations

OperationDescriptionRequires ValueRequires Attribute
addClassAdd a CSS classYesNo
removeClassRemove a CSS classYesNo
toggleClassToggle a CSS classYesNo
setAttributeSet an attributeYesYes
removeAttributeRemove an attributeNoYes

Examples

json
// Add dark mode class to html element
{
  "do": "dom",
  "operation": "addClass",
  "selector": { "expr": "lit", "value": "html" },
  "value": { "expr": "lit", "value": "dark" }
}

// Remove light mode class
{
  "do": "dom",
  "operation": "removeClass",
  "selector": { "expr": "lit", "value": "html" },
  "value": { "expr": "lit", "value": "light" }
}

// Set data attribute
{
  "do": "dom",
  "operation": "setAttribute",
  "selector": { "expr": "lit", "value": "body" },
  "attribute": "data-theme",
  "value": { "expr": "state", "name": "theme" }
}

Import Step

Dynamically imports an external JavaScript module at runtime.

json
{
  "do": "import",
  "module": "monaco-editor",
  "result": "monaco",
  "onSuccess": [
    { "do": "set", "target": "editorReady", "value": { "expr": "lit", "value": true } }
  ]
}
NameTypeRequiredDefaultDescription
do"import"Yes-Step type identifier.
modulestringYes-Module name (must match a key in externalImports).
resultstringYes-Variable name to store the imported module.
onSuccessActionStep[]No-Steps to execute after successful import.
onErrorActionStep[]No-Steps to execute on import failure.

Example: Loading Monaco Editor

json
{
  "externalImports": {
    "monaco-editor": "https://cdn.jsdelivr.net/npm/monaco-editor@0.52.0/+esm"
  },
  "lifecycle": {
    "onMount": "initEditor"
  },
  "actions": [{
    "name": "initEditor",
    "steps": [{
      "do": "import",
      "module": "monaco-editor",
      "result": "monaco",
      "onSuccess": [{
        "do": "call",
        "target": { "expr": "var", "name": "monaco", "path": "editor.create" },
        "args": [
          { "expr": "ref", "name": "editorContainer" },
          { "expr": "lit", "value": { "language": "json", "theme": "vs-dark" } }
        ],
        "result": "editorInstance"
      }]
    }]
  }]
}

Call Step

Calls a JavaScript function on an imported module or DOM element.

json
{
  "do": "call",
  "target": { "expr": "var", "name": "monaco", "path": "editor.create" },
  "args": [
    { "expr": "ref", "name": "container" },
    { "expr": "lit", "value": { "language": "json" } }
  ],
  "result": "editor"
}
NameTypeRequiredDefaultDescription
do"call"Yes-Step type identifier.
targetExpressionYes-Expression that evaluates to a function.
argsExpression[]No-Array of argument expressions.
resultstringNo-Variable name to store the return value.
onSuccessActionStep[]No-Steps to execute after successful call.
onErrorActionStep[]No-Steps to execute on error.

Examples

json
// Call a method on an imported library
{
  "do": "call",
  "target": { "expr": "state", "name": "editor", "path": "getValue" },
  "result": "editorValue"
}

// Call with arguments
{
  "do": "call",
  "target": { "expr": "state", "name": "chart", "path": "update" },
  "args": [{ "expr": "state", "name": "chartData" }]
}

Subscribe Step

Subscribes to events from an external JavaScript object.

json
{
  "do": "subscribe",
  "target": { "expr": "state", "name": "editor" },
  "event": "onDidChangeModelContent",
  "action": "onCodeChange"
}
NameTypeRequiredDefaultDescription
do"subscribe"Yes-Step type identifier.
targetExpressionYes-Expression that evaluates to an object with event methods.
eventstringYes-Event method name to subscribe to.
actionstringYes-Action name to execute when the event fires.

Example: Monaco Editor Change Events

json
{
  "actions": [
    {
      "name": "setupEditor",
      "steps": [
        {
          "do": "subscribe",
          "target": { "expr": "state", "name": "editor" },
          "event": "onDidChangeModelContent",
          "action": "onCodeChange"
        }
      ]
    },
    {
      "name": "onCodeChange",
      "steps": [
        {
          "do": "call",
          "target": { "expr": "state", "name": "editor", "path": "getValue" },
          "result": "currentCode",
          "onSuccess": [
            { "do": "set", "target": "code", "value": { "expr": "var", "name": "currentCode" } }
          ]
        }
      ]
    }
  ]
}

Dispose Step

Manually disposes of a resource (cleanup subscriptions, destroy editors, etc.).

json
{
  "do": "dispose",
  "target": { "expr": "state", "name": "editor" }
}
NameTypeRequiredDefaultDescription
do"dispose"Yes-Step type identifier.
targetExpressionYes-Expression that evaluates to an object with a dispose() method.

Example: Cleanup on Unmount

json
{
  "lifecycle": {
    "onUnmount": "cleanup"
  },
  "actions": [{
    "name": "cleanup",
    "steps": [
      { "do": "dispose", "target": { "expr": "state", "name": "subscription" } },
      { "do": "dispose", "target": { "expr": "state", "name": "editor" } }
    ]
  }]
}

Clipboard Step

Provides access to the system clipboard for reading and writing text content.

json
{
  "do": "clipboard",
  "operation": "write",
  "value": { "expr": "state", "name": "textToCopy" }
}
NameTypeRequiredDefaultDescription
do"clipboard"Yes-Step type identifier.
operation"write" | "read"Yes-Clipboard operation to perform.
valueExpressionNo-Value to write to clipboard (required for 'write' operation).
resultstringNo-Variable name to store read result (for 'read' operation).
onSuccessActionStep[]No-Steps to execute on successful clipboard operation.
onErrorActionStep[]No-Steps to execute if clipboard operation fails. Error is available as 'error' variable.

Example: Copy to Clipboard

json
{
  "name": "copyLink",
  "steps": [
    {
      "do": "clipboard",
      "operation": "write",
      "value": { "expr": "state", "name": "shareUrl" },
      "onSuccess": [
        { "do": "set", "target": "copied", "value": { "expr": "lit", "value": true } }
      ],
      "onError": [
        { "do": "set", "target": "copyError", "value": { "expr": "var", "name": "error", "path": "message" } }
      ]
    }
  ]
}

Example: Paste from Clipboard

json
{
  "name": "pasteText",
  "steps": [
    {
      "do": "clipboard",
      "operation": "read",
      "result": "clipboardText",
      "onSuccess": [
        { "do": "set", "target": "inputValue", "value": { "expr": "var", "name": "clipboardText" } }
      ]
    }
  ]
}

If Step

Conditionally executes steps based on a condition.

json
{
  "do": "if",
  "condition": { "expr": "state", "name": "isLoggedIn" },
  "then": [
    { "do": "navigate", "url": { "expr": "lit", "value": "/dashboard" } }
  ],
  "else": [
    { "do": "navigate", "url": { "expr": "lit", "value": "/login" } }
  ]
}
NameTypeRequiredDefaultDescription
do"if"Yes-Step type identifier.
conditionExpressionYes-Expression that evaluates to a boolean.
thenActionStep[]Yes-Steps to execute when condition is true.
elseActionStep[]No-Steps to execute when condition is false.

Examples

json
// Conditional theme application
{
  "do": "if",
  "condition": { "expr": "var", "name": "savedTheme" },
  "then": [
    { "do": "set", "target": "theme", "value": { "expr": "var", "name": "savedTheme" } },
    {
      "do": "dom",
      "operation": "addClass",
      "selector": { "expr": "lit", "value": "html" },
      "value": { "expr": "var", "name": "savedTheme" }
    }
  ]
}

// Validation before submit
{
  "do": "if",
  "condition": {
    "expr": "bin",
    "op": "!=",
    "left": { "expr": "state", "name": "email" },
    "right": { "expr": "lit", "value": "" }
  },
  "then": [
    { "do": "fetch", "url": { "expr": "lit", "value": "/api/submit" }, "method": "POST" }
  ],
  "else": [
    { "do": "set", "target": "error", "value": { "expr": "lit", "value": "Email is required" } }
  ]
}

SetPath Step

Updates a value at a specific path within a nested object or array. Unlike set which replaces the entire target, setPath allows surgical updates to deeply nested state.

json
{
  "do": "setPath",
  "target": "todos",
  "path": { "expr": "lit", "value": [0, "completed"] },
  "value": { "expr": "lit", "value": true }
}
NameTypeRequiredDefaultDescription
do"setPath"Yes-Step type identifier.
targetstringYes-State field containing the array or object.
pathExpressionYes-Expression that evaluates to a path. Can be a string (dot notation like "address.city"), an array of keys/indices, or an array containing expressions for dynamic segments.
valueExpressionYes-New value to set at the path.

Why Use setPath?

The setPath step solves a common problem: updating a single field in an array item without replacing the entire item. This is more efficient and preserves other fields.

ApproachCodeResult
replaceAtReplaces entire itemLoses other fields unless you rebuild the object
setPathUpdates single fieldPreserves all other fields automatically

Examples

json
// Toggle completion status of a todo item (dynamic index from payload)
{
  "do": "setPath",
  "target": "todos",
  "path": { "expr": "lit", "value": [{ "expr": "var", "name": "index" }, "completed"] },
  "value": {
    "expr": "not",
    "operand": { "expr": "var", "name": "todo", "path": "completed" }
  }
}

// Update username in a nested user object (literal index)
{
  "do": "setPath",
  "target": "users",
  "path": { "expr": "lit", "value": [0, "profile", "name"] },
  "value": { "expr": "state", "name": "newName" }
}

// Update using dot notation string path
{
  "do": "setPath",
  "target": "config",
  "path": { "expr": "lit", "value": "settings.display.theme" },
  "value": { "expr": "lit", "value": "dark" }
}

// Update score for a specific player (dynamic index)
{
  "do": "setPath",
  "target": "players",
  "path": { "expr": "lit", "value": [{ "expr": "var", "name": "playerId" }, "score"] },
  "value": {
    "expr": "bin",
    "op": "+",
    "left": { "expr": "var", "name": "player", "path": "score" },
    "right": { "expr": "lit", "value": 10 }
  }
}

Send Step

Sends a message through a WebSocket connection. See Connections for full WebSocket documentation.

json
{
  "do": "send",
  "connection": "chat",
  "data": { "expr": "state", "name": "messageInput" }
}
NameTypeRequiredDefaultDescription
do"send"Yes-Step type identifier.
connectionstringYes-Name of the connection to send through (must match a key in connections).
dataExpressionYes-Data to send. Objects are automatically JSON stringified.

Example

json
{
  "name": "sendChatMessage",
  "steps": [
    {
      "do": "send",
      "connection": "chat",
      "data": { "expr": "state", "name": "messageInput" }
    },
    {
      "do": "set",
      "target": "messageInput",
      "value": { "expr": "lit", "value": "" }
    }
  ]
}

Close Step

Closes a WebSocket connection. See Connections for full WebSocket documentation.

json
{
  "do": "close",
  "connection": "chat"
}
NameTypeRequiredDefaultDescription
do"close"Yes-Step type identifier.
connectionstringYes-Name of the connection to close.

Example

json
{
  "name": "disconnectChat",
  "steps": [
    {
      "do": "close",
      "connection": "chat"
    },
    {
      "do": "set",
      "target": "isConnected",
      "value": { "expr": "lit", "value": false }
    }
  ]
}