Dashboard Guide
Dashboards are drag-and-drop layouts with live widgets that display real-time data from your devices.
AI Generation
The AI chat can create and edit dashboards on request. Ask something like:
Build me a dashboard for the robot and the webcam — include a position viewer, a speed slider, a reset button, and a live camera feed.
The AI discovers available connectors via list_connectors + get_connector_schema, writes a .dashboard.json file with write_dashboard, and drops it into workspace/dashboards/ ready to open. Follow-ups like "add a chart of voltage" round-trip through read_dashboard → write_dashboard so existing widgets are preserved. The same three tools (list_dashboards, read_dashboard, write_dashboard) are exposed over MCP for Claude Desktop / Claude Code sessions.
Creating a Dashboard
Create a .dashboard.json file in workspace/dashboards/:
{
"name": "Lab Monitor",
"widgets": [
{
"id": "voltage-gauge",
"type": "gauge",
"x": 0, "y": 0, "w": 4, "h": 3,
"config": {
"connector": "psu",
"property": "voltage",
"label": "Voltage",
"min": 0, "max": 30, "unit": "V"
}
}
]
}Open the dashboard file in the app to see the live widget layout.
Widget Types
Display Widgets (read-only)
| Type | Description | Key Config |
|---|---|---|
| gauge | Semi-circular gauge with needle and color zones | min, max, unit, zones |
| text | Formatted value display with label and unit | label, unit |
| chart | Time-series line chart (using uPlot), auto-scrolling | bindings[], duration, yMin, yMax |
| scope | Oscilloscope with built-in V/div, T/div knobs, Y-position, Run/Stop, Auto | ch1, ch2, ch3, mode, persistence, lineWidth, gridLines |
| indicator | LED-style on/off status indicator (red/green/amber) | label |
| object-viewer | Collapsible JSON tree view of complex data | fontSize, decimals |
Interactive Widgets (read + write)
| Type | Description | Key Config |
|---|---|---|
| slider | Horizontal slider to set a numeric property | min, max, step |
| knob | Rotary dial with arc indicator, drag to change | min, max |
| button | Trigger an action on a connector (text auto-derived from binding) | label, text, mode, activeColor, action binding |
| toggle | On/off switch with LED-style indicator | boolean property binding |
| script-control | Start/stop button for a named script | scriptName, text, activeColor |
Streaming Widgets
| Type | Description | Key Config |
|---|---|---|
| canvas | Displays video/image streams; supports interactive vision annotation | mode ("image"), stream, visionConnector (optional) |
| terminal | Scrolling monospace text display with input field | stream, maxLines, fontSize, sendAction |
Widget Layout
Widgets are positioned on a 12-column grid:
x,y— grid position (columns, rows)w,h— size in grid units (width, height)
Drag widgets to reposition them. Resize by dragging the corner handle.
Data Binding
Widgets bind to connector properties via the config object:
connector— the connector name (e.g.,"psu")property— the property to display (e.g.,"voltage")binding— alternative path format:"connector.property"(e.g.,"robot.position[0]")
Properties with poll: true in the connector config update the widget automatically.
Stream Binding
For canvas and terminal widgets, use a stream config to subscribe to real-time data:
{
"type": "canvas",
"config": {
"label": "Webcam",
"mode": "image",
"stream": "webcam:frames"
}
}Terminal Send Input
Terminal widgets are bidirectional — the scrolling display shows a stream and, when a sendAction binding is set, an input bar appears below it. Pressing Enter invokes the bound connector action with the typed text.
{
"type": "terminal",
"config": {
"label": "Serial Monitor",
"stream": "serial-monitor:output",
"sendAction": "serial-monitor.sendLine"
}
}Drag a connector action (e.g. serial-monitor.sendLine or serial-probe.send) onto the sendAction field to wire it up. The input bar is hidden when sendAction is empty — so existing read-only terminals stay unchanged.
Vision Annotation
To enable direct object teaching on a canvas widget, add visionConnector to the config:
{
"type": "canvas",
"config": {
"label": "Vision Trainer",
"mode": "image",
"stream": "vision:annotated",
"visionConnector": "vision"
}
}When visionConnector is set, an annotation toolbar appears on the canvas. Users can draw bounding boxes to teach objects, click labels to select, and delete tracked objects — all without AI. See the AI guide for the full workflow.
A pre-built Vision Annotation dashboard (vision-annotation.dashboard.json) demonstrates the full annotation workflow with side-by-side raw and annotated feeds, FPS monitoring, live detection data, and script controls for the multi-tracker and contour detection demos.
Script Control Binding
Script control widgets bind to a script by name:
{
"type": "script-control",
"config": {
"scriptName": "monitor",
"text": "Monitor",
"activeColor": "#4caf50"
}
}Dashboard JSON Format
Full example with multiple widget types:
{
"name": "Robot Control Panel",
"version": 1,
"gridCols": 12,
"rowHeight": 40,
"widgets": [
{
"id": "w1",
"type": "gauge",
"layout": { "x": 0, "y": 0, "w": 3, "h": 4 },
"config": {
"label": "Joint 1 Angle",
"binding": "robot.joints[0]",
"min": -180, "max": 180, "unit": "°",
"zones": [
{ "min": -180, "max": -90, "color": "var(--error)" },
{ "min": -90, "max": 90, "color": "var(--success)" },
{ "min": 90, "max": 180, "color": "var(--error)" }
]
}
},
{
"id": "w2",
"type": "chart",
"layout": { "x": 3, "y": 0, "w": 6, "h": 4 },
"config": {
"label": "Position History",
"bindings": ["robot.position[0]", "robot.position[1]", "robot.position[2]"],
"duration": 30,
"yMin": -500, "yMax": 500, "unit": "mm"
}
},
{
"id": "w-scope",
"type": "scope",
"layout": { "x": 3, "y": 4, "w": 8, "h": 7 },
"config": {
"label": "Waveform",
"ch1": "sensor.voltage",
"ch2": "sensor.current",
"mode": "scroll",
"persistence": 0.4,
"lineWidth": 1.5,
"gridLines": true
}
},
{
"id": "w3",
"type": "terminal",
"layout": { "x": 0, "y": 4, "w": 6, "h": 4 },
"config": {
"stream": "serial-monitor:output",
"maxLines": 500,
"fontSize": "medium",
"showTimestamps": true,
"sendAction": "serial-monitor.sendLine"
}
}
]
}Editing
- Edit mode: Click the edit button to toggle layout editing
- Add widgets: Click the add button and select a widget type
- Configure: Click a widget to edit its config (connector, property, appearance)
- Delete: Select a widget and press Delete or use the remove button
- Save: Changes are saved to the
.dashboard.jsonfile automatically
Virtual Store Pattern
Use the GUI driver to create virtual connectors that bridge scripts and dashboards without hardware:
// workspace/connectors/store.js
export default {
driver: "GUI",
config: {
widgets: [
{ name: "value1", type: "gauge", label: "Value 1", min: 0, max: 100 },
{ name: "input", type: "slider", label: "Input", min: 0, max: 100 },
],
},
};Scripts write: store.value1 = 42 → Dashboard gauge updates automatically.
Cross-Panel Drag-and-Drop
| Drag Source | Drop Target | Result |
|---|---|---|
| Hardware property (from Connector Browser) | Widget on dashboard canvas | Sets widget binding automatically |
| Hardware stream | Canvas/Video widget on dashboard canvas | Sets stream + switches to image mode |
| Hardware property (from Connector Browser) | Binding field in config panel | Sets widget binding |
| Hardware stream | Stream field in config panel | Sets stream binding |
| Script (from Scripts panel) | Dashboard grid | Creates script-control widget |
| Hardware property | Script editor | Inserts connector("x").prop code |