VIBECANVAS

Widgets and Actors

Learn how generated widgets use actors for live backend behavior.

Vibecanvas widgets are small generated app surfaces on the infinite canvas. A widget can look like a chart, form, board, gallery, table, chat, timer, or control panel, but the important part is that it can also have live behavior behind it.

Each live widget has two parts:

  • Widget UI: the visible interface on the canvas.
  • Actor backend: the local logic that owns state, handles actions, and emits updates.

What a widget is

A widget is the thing you place and arrange on the canvas. It is the user-facing app surface: buttons, fields, lists, charts, and other interactive UI.

When you ask Vibecanvas to generate a widget, it can create the UI and the backing actor together. That makes the result more than a mockup. The widget can send actions to its actor, and the actor can update the widget with new state.

What an actor is

An actor is the backend brain for one widget instance. Think of it as the widget’s private local service.

Actors are meant to:

  • Store the widget’s state and data.
  • Validate messages sent by the widget UI.
  • Run state transitions one at a time.
  • Update data after an accepted action.
  • Emit messages that other connected actors may receive.

For example, a booking widget might send selectDate or confirmBooking messages. Its actor decides whether those messages are valid, updates the booking data, and sends the latest state back to the widget UI.

Each widget instance gets its own actor instance and its own data. Two booking widgets placed on the same canvas do not automatically share selected dates, form values, or internal state. If widgets need to coordinate, they should communicate through explicit actor messages or connections rather than reading each other’s private data.

How the pieces talk

The basic loop is:

Widget UI --sends message--> Actor backend
Actor backend --updates state/data--> Widget UI
Actor backend --emits output--> Connected actors

The widget UI should only need to know a small API:

  • Read the actor state.
  • Read the actor context data.
  • Send a named message with a JSON payload.

Vibecanvas handles the lower-level details: finding the right actor instance, validating payloads, routing events, syncing snapshots, and keeping the canvas element connected to its backend.

Why this matters

This model lets you generate many small app widgets without turning the canvas into a developer workspace. Each widget can stay focused, while actors make those widgets live.

Use one widget for one clear job:

  • A dashboard chart with live filter state.
  • A queue that accepts, rejects, or prioritizes items.
  • A form that validates and saves submissions.
  • A gallery that tracks selection and metadata.
  • A control panel that sends actions to another widget.

When a workflow grows, generate another widget and place it nearby instead of making one widget do everything.

Widget UI limits

Widget UI code runs in an Arrow sandbox. That sandbox is intentionally limited.

The widget can render UI with Arrow templates and send serialized messages through the Vibecanvas widget SDK. It does not get direct access to the browser page, the real DOM, the canvas engine, internal services, the database, or Bun process objects.

This means generated UI should not depend on direct calls such as reading document, mutating DOM nodes manually, reaching into the canvas, or calling private host APIs. The host page owns the real DOM and canvas. The sandbox communicates with Vibecanvas through a controlled bridge.

The practical rule is:

  • Put visible interaction in the widget UI.
  • Put state changes and backend behavior in the actor.
  • Communicate with JSON messages.
  • Let Vibecanvas own canvas placement, rendering portals, event routing, and security boundaries.

Actor limits

Actors run locally and can perform backend work through the capabilities Vibecanvas provides. They should still be designed as small state machines with clear messages, not as open-ended scripts.

Good actor behavior is predictable:

  • Each input message has a known payload shape.
  • Invalid messages are rejected instead of changing state.
  • State transitions are explicit.
  • Data updates happen through the actor runtime.
  • Output messages are JSON-serializable.

That structure makes generated widgets easier to inspect, regenerate, connect, and reuse.