Vettero
Build

Widgets

Hosted HTML or external URL pages for the home dashboard and sidebar.

Widgets are custom workspace pages that run in a sandboxed iframe. Content is either hosted HTML (with window.vt injected) or an external URL that uses the same protocol. Bind queries, functions, agents, workflows, and blocks — then call them from the iframe without exposing workspace credentials.

Use them for interactive dashboards, ops consoles, and custom forms on the home grid or as sidebar pages. These are not chat widgets (Liquid UIs inside chat messages).

When to use

  • Build custom workspace pages that need live table data or long-running jobs
  • Reuse the same queries, functions, agents, and workflows from the browser
  • Place the UI on the dashboard and/or as one or more sidebar pages

The iframe never gets raw API keys. Only keys listed under Bound resources and Jobs are callable through vt.

Create a widget

Open Build → Widgets and click New.

  1. Enter a Name and optional Description.
  2. Click create — Vettero creates a Hosted widget and opens the editor.

On the list, filter by All, Hosted, or URL. Widgets are workspace-only; there is no agent-scoped iframe widget panel.

Configure the widget

From the widget detail page, click Edit.

SectionWhat you configure
Name / DescriptionIdentity in lists and Studio
SourceHosted HTML or External URL
HTML document or URLFull HTML when hosted; required URL when external
Input args schemaJSON Schema for instance args → vt.getArgs()
Bound resourcesOne-shot calls via vt.run*
JobsLong-running runs via vt.startJob / watch / cancel
PreviewLive preview of the widget

For hosted widgets, the vt SDK is injected before </body>. New hosted widgets without custom HTML get a default document that demos theme helpers and vt.getArgs().

Add sidebar integrations

On the widget detail page, manage Sidebar integrations. Each integration is a sidebar page with its own args and access control.

SettingWhat it does
NameLabel in the sidebar
IconOptional icon
Access rolesWho can open it; empty = all roles
Input argsValues matching the widget’s input schema

With no integrations, the widget is not listed in the sidebar pool. You can still pin it on the Home dashboard. Dashboard tiles and integrations both supply instance args for vt.getArgs().

You can also place widgets under Workspace Settings → Sidebar Items (type Widget).

Bind resources and jobs

Bound resources (one-shot)

Same pattern as functions: unique keys, then call with vt.runQuery, vt.runFunction, vt.runWorkflow, vt.runAgent, or vt.runBlock.

TypeNotes
QueryAny workspace query
FunctionAny workspace function
Agent / WorkflowMust use the general channel
BlockTool-capable block; pick a Service when needed

runAgent / runWorkflow wait for completion (up to about 5 minutes) and throw if the run fails or is waiting for human approval. runBlock does not support human-in-the-loop interrupts.

Jobs (async)

Jobs are for long-running work. Add a key, type (Workflow, Agent, or Function), target, and scope:

ScopeMeaning
Per userOne active run per caller
GlobalOne shared active run per job key

Starting a job while one is already active for that scope fails with Job already running. Status values: pending, running, finished, failed, cancelled. Jobs cannot bind Query or Block.

Match the workspace theme

Hosted widgets receive the current workspace theme as CSS variables, including the company primary color and dark mode. Use the built-in classes for cards and controls. Use the variables when you need custom layout. Do not hardcode colors.

ClassWhat it is
vt-gridAuto-fit card grid
vt-cardBordered panel
vt-label / vt-valueMetric label and value
vt-mutedSecondary text
vt-btn / vt-btn-primaryButtons
vt-inputText input

Variables include --vt-bg, --vt-surface, --vt-surface-muted, --vt-border, --vt-text, --vt-text-muted, --vt-primary, --vt-primary-contrast, --vt-radius, and --vt-space. They update when the theme changes. vt.getTokens() returns the same values if a script needs them.

<div class="vt-grid">
  <div class="vt-card">
    <div class="vt-label">Total balance</div>
    <div class="vt-value">—</div>
  </div>
</div>

Use the widget SDK

Hosted widgets get window.vt automatically. URL widgets must speak the same vettero-widget postMessage protocol (or load the same SDK).

MethodWhat it does
vt.getArgs()Instance args from the dashboard tile or sidebar integration
vt.isDark() / vt.getTokens() / vt.onThemeChange(cb)Theme flag, current design tokens, and a listener cb(dark, tokens)
await vt.getUser()Current user profile
await vt.runQuery / runFunction / runWorkflow / runAgent / runBlockBound resources
await vt.watchQuery(key, input?, onData)Re-runs when related table rows change
await vt.startJob / getJob / getCurrentJob / listJobs / cancelJobJob lifecycle
await vt.watchJob(key, runId?, onUpdate)Watch a job; omit runId to watch the current run
Use vt.runQuery to run a bound query. Add vt.watchQuery to watch for related table-row changes and make a live widget.
<script>
  async function load() {
    const args = vt.getArgs()
    const { rows, total } = await vt.runQuery('orders', { status: args.status })
    const job = await vt.startJob('sync', { status: args.status })
    console.log(total, job.status)
  }
  load()
</script>

Place on the home dashboard

On Home, use Add widget / Manage widgets to pin widgets as tiles. Each tile can pass its own args matching the input schema.

Limits

  • Agents and workflows bound as resources or jobs must use the general channel.
  • Jobs cannot bind query or block types.
  • A second startJob while an active run exists for that scope fails.

Where widgets are used

PlaceHow
Home dashboardTile with the widget and optional args
SidebarEach Sidebar integration, or Settings → Sidebar Items
Copyright © 2026