Job & Dashboard Reference
Dashboard YAML
Reference every top-level dashboard YAML key: pages, widgets, scope profiles, shared_queries, navbar_ctas, and public sharing flags.
Dashboard YAML
Dashboards are YAML-defined widget pages bound to Jobs. Definitions are authored on dashboard templates attached to a Job Template and snapshotted onto each Job's dashboards rows at job creation, with ${VAR} substitution from the job's arguments. parseDashboardYaml in src/dashboard-parser.ts enforces this schema; the document may start with a top-level dashboard: key or be a bare dashboard object.
This page covers the document structure. Widget configuration lives in the Widgets overview and its group pages; the authoring guide is Authoring dashboards.
Top-level keys
| Key | Type | Required | Description |
|---|---|---|---|
title |
string | No | Display title rendered in the page header. |
description |
string | No | Display description. |
navbar_ctas |
array | No | Header action group for the public share surface (see below). |
refresh_interval_seconds |
number | No | Dashboard-level polling interval. |
scope |
object | No | Named read-only filter profiles: profile name → connector name → filter fields (literal or JSONata string). |
default_scope |
string | No | Profile applied when a widget omits scope. Must name a defined profile. |
allow_public_input |
boolean | No | Allow input widgets to be edited through the public share link (also gated by the server kill switch). |
shared_queries |
object | No | Named read-only connector calls resolved once per refresh and shared by widgets. |
pages |
array | No | Multi-page layout. Mutually exclusive with top-level widgets. |
widgets |
array | No | Legacy single-page widget list, normalized into one page with id: main. |
pages
Prefer pages[] for multi-section dashboards. Each page:
| Key | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Stable page identity; unique across the document. |
title |
string | Yes | Navigation label. |
widgets |
array | Yes | Ordered widget list. |
public |
boolean | No | Set false to hide the page (and its widgets) from public share links. Default: visible. |
dashboard:
title: Ops console
refresh_interval_seconds: 60
pages:
- id: overview
title: Overview
widgets:
- id: intro
type: heading
title: Status
- id: data
title: Data
public: false
widgets:
- id: tickets
type: explorer
data:
connector: mongo
resource: ticketsWidget ids must be unique across the whole document, not just within a page. A document cannot declare both pages and top-level widgets.
Widget types
Fourteen widget types are registered. Their per-type configuration is documented on three group pages:
| Type | Group | Purpose |
|---|---|---|
heading |
Display widgets | Section labels and instructional callouts. |
stat |
Display widgets | Single numeric result. |
progress |
Display widgets | Current/total ratio bar. |
steps |
Display widgets | Horizontal process stepper. |
people |
Display widgets | Contact cards. |
bar_chart |
Chart and table widgets | Bar chart over an array of records. |
line_chart |
Chart and table widgets | Line chart over an array of records. |
pie_chart |
Chart and table widgets | Pie chart over an array of records. |
table |
Chart and table widgets | Bounded result set with declared columns. |
form |
Input and action widgets | Typed fields writing a job_config object. |
field_mapping |
Input and action widgets | Source-to-target mapping editor writing a job_config array. |
action |
Input and action widgets | Declarative server-executed button. |
task_progress |
Input and action widgets | Latest run status for one job task key. |
explorer |
Input and action widgets | Curated pageable data browser. |
Keys shared by every widget (id, title, width, scope, refresh_interval_seconds, and data binding) are documented once on the Widgets overview.
scope and default_scope
Scope profiles inject read-only filters into widget connector calls, so one dashboard definition can serve different data slices:
dashboard:
default_scope: source
scope:
source: |
{
"mongo": {
"job_id": arguments.job_id
}
}- A widget without a
scopekey usesdefault_scope. scope: <name>on a widget selects a specific profile;scope: nullopts the widget out of injection.default_scopemust name a defined profile; otherwise parsing fails withdefault_scope "<name>" is not defined in scope.
Scope is merged into read-only connector calls (Mongo filter, aggregate $match prefix, Truto top-level args). SQLite select does not auto-inject scope because raw SQL is opaque.
shared_queries
Named read-only connector calls resolved once per refresh and cached. Widgets reference an entry with shared_query: <name> and derive their value with a JSONata expression; the shared result is bound as data in the widget's expression context.
dashboard:
shared_queries:
tickets_facet:
connector: mongo
method: aggregate
args:
collection: zendesk_tickets
pipeline:
- "$facet":
total: [{ "$count": "count" }]
migrated:
- { "$match": { "status": "migrated" } }
- { "$count": "count" }
widgets:
- id: tickets_total
type: stat
shared_query: tickets_facet
value_expr: "$exists(data[0].total[0]) ? data[0].total[0].count : 0"navbar_ctas
Optional action group rendered in the public dashboard header:
| Key | Type | Required | Description |
|---|---|---|---|
label |
string | Yes | Button or link text. |
href |
string | Yes | Must be an http(s), mailto:, tel:, or relative URL. |
variant |
string | No | button (default) or link. |
icon |
string | No | Icon name. |
text |
string | No | Secondary display text. |
navbar_ctas:
- label: Support
variant: button
icon: mail
href: mailto:[email protected]
text: [email protected]Attachment and sharing model
- Dashboard templates belong to a Job Template; Dashboards belong to a Job. Creating a Job snapshots each active dashboard template onto a
dashboardsrow. - A per-dashboard share token (
POST /api/dashboards/:id/share) exposes a public read-only view. The public payload is sanitized: connector call configs,shared_queries,scope, and action dispatch internals are stripped; pages withpublic: falseand actions withoutallow_public: trueare omitted. allow_public_input: trueallows input widgets to be edited through the share link, and only when the server-side kill switchENVOY_PUBLIC_DASHBOARD_INPUT_ENABLEDis also enabled.
Validation errors
| Message | Cause |
|---|---|
dashboard.pages must be a non-empty array |
pages is present but empty or not an array. |
dashboard cannot have both pages and top-level widgets |
Choose one layout style. |
dashboard.pages[<i>].id is required / .title is required / .widgets must be an array |
A page is missing a required key. |
Duplicate page id: <id> |
Two pages share an id. |
Duplicate widget id: <id> |
Two widgets share an id anywhere in the document. |
dashboard.widgets must be an array |
Neither pages nor a widgets array is present. |
widgets[<i>].type must be one of: ... |
Unknown widget type. |
widgets[<i>].id is required |
A widget is missing id. |
dashboard.navbar_ctas[<i>].href must be an http(s), mailto, tel, or relative URL |
Unsafe CTA URL. |
default_scope "<name>" is not defined in scope |
default_scope names a missing profile. |
Related
- Widgets overview — the 14 widget types and shared widget keys
- Authoring dashboards — design, testing, and public-share guidance
- job_config schema — the values input widgets read and write