Dashboard JSON
A dashboard is a single JSON object. This page is the top-level contract; the authoritative machine-readable version is the published JSON Schema.
Top level
{
"name": "My dashboard",
"description": "Optional.",
"version": "1.0.0",
"settings": { "interval_enabled": false },
"layout": [ /* tiles */ ]
}| Field | Required | Description |
|---|---|---|
name | yes | Human-friendly title (1–140 chars). |
description | no | Optional summary. |
version | no | Content/schema version for future migrations. |
settings | no | Dashboard runtime settings (see below). |
layout | yes | Array of one or more tiles. |
Settings
"settings": { "interval_enabled": true, "interval_ms": 60000 }| Field | Description |
|---|---|
interval_enabled | If true, the dashboard may refresh tiles on an interval. |
interval_ms | Dashboard refresh interval in ms (5000–3600000). Required when interval_enabled is true. |
Tiles
Each entry in layout is a tile. The minimum is an id, a position, and a block:
{
"id": "notes",
"position": { "row": 0, "order": 0, "width": 12 },
"block": { "type": "markdown", "config": { "content": "# Hello" } }
}A tile may also carry title, card, load, exec, query, depends_on, triggered_by, tags, artifact, and controls. See Tiles for the full field reference.
Responsive layout & orientation
Default behavior (no configuration needed). On wide viewports, tiles lay out using their width (the 12-column grid). On narrow viewports — a phone, or whenever the usable width shrinks, such as when an AI side panel is open next to the dashboard — tiles stack vertically, full-width, in row then order. This reflow is purely presentational: your dashboard JSON is unchanged, and desktop layouts are unaffected. Most dashboards need nothing more.
Two optional fields (schema 1.2.0) let you tune that narrow/mobile experience. Both are additive — omit them and the default stacking above applies.
position.portrait — per-tile overrides applied only in mobile portrait:
"position": {
"row": 1, "order": 2, "width": 12,
"portrait": { "order": 1, "width": 12, "height": 340, "align": "center" }
}| Field | Type | Meaning |
|---|---|---|
order | int | Reorder within the same row, in portrait |
width | int (1–12) | Tile width in portrait (same 12-column convention) |
height | int (160–1200) | Tile height in pixels in portrait |
align | start / center / end | Cross-axis alignment in portrait |
Overrides stay within the existing row; there is no free positioning. Outside mobile portrait they are ignored.
position.hide_on — hide a tile in a given orientation:
"position": { "row": 0, "order": 0, "width": 6, "hide_on": "portrait" }"portrait" or "landscape". Absent = always shown. Note that desktop monitors count as landscape, so "landscape" hides on desktop too — use "portrait" to simply declutter narrow/portrait views.
Source values
Anywhere the schema allows it, a literal can be replaced with a dynamic reference resolved by the runtime:
{ "?source": "region_options" }StrataBI looks the id up in the source registry, loads the payload from S3, and substitutes the value before execution. See Inputs & parameters.
Validation
Dashboards validate against dashboard.schema.json (JSON Schema 2020-12). Invalid documents are rejected before they run — validate at author time to catch mistakes early.
Shaleio