Skip to content

Dashboards & charts

Charts and dashboards are how ad-hoc analysis becomes something the whole workspace looks at. The pieces stack: a saved query produces rows, a chart gives one query a visual shape, a dashboard arranges charts and query tables on a grid, and the workspace home page can pin those same tiles as the first thing everyone sees. Each layer is a separate, reusable object — change the query and every chart, dashboard, and home-page tile built on it updates with it.

If you only remember one thing: a dashboard never carries data or grants access to it. Every tile runs its query as the person viewing it, at the moment they view it. Sharing a dashboard shares the definition, not the results — a viewer whose record visibility is restricted sees “Not available for your access level” where the numbers would be.


Capability Action Default roles
View charts charts:read Admin, Member, Reader
Create/edit/delete charts charts:manage Admin, Member
View dashboards dashboards:read Admin, Member, Reader
Create/edit/delete dashboards dashboards:manage Admin, Member
View saved queries (chart sources) savedQueries:read Admin, Member, Reader
See the data behind a tile query:execute + unrestricted record visibility See below
Configure the workspace home page customization:manage Admin
Open the chart editor page builder:access Admin (grantable via custom roles)

Charts, dashboards, and saved queries have no per-object ownership or sharing controls: every one of them is visible workspace-wide to anyone holding the read action, and editable by anyone holding the manage action. The creator is recorded but grants no special rights. If you need a private-to-me analysis, keep it as SQL in the query editor rather than saving it as a shared object.


Charts are authored on the Charts page in the builder area (Admin → Charts, behind builder:access). A chart is three things:

  1. A data source — either a saved query (recommended: reusable, centrally editable) or inline SQL written just for this chart. A chart backed by a saved query inherits the query’s template variables; an inline-SQL chart carries its own variable definitions.
  2. A chart typebar, line, area, or pie.
  3. Display configuration — for bar/line/area: which column is the X axis and one or more Y series, each with its own colour and optional label (multiple series plot side by side with a legend). For pie: which column supplies the segment labels and which the values.

The editor previews the chart live against real query results, so you shape the SQL and the axes together — GROUP BY in the query typically supplies the X axis, aggregates supply the Y series. Date-like columns are detected and formatted as dates on the axis automatically.

Chart cards on the Charts page run their query for a live preview, and show usage chips listing the dashboards each chart appears on. Duplicate copies a chart when you want to change one without touching the dashboards built on the original.

API: GET /charts, POST /charts, PUT /charts/{chartId}, DELETE /charts/{chartId}.


Dashboards live in the end-user area at Dashboards — no builder access needed to view or (with dashboards:manage) to compose them.

A dashboard is a named grid of tiles. Each tile is one of:

  • Chart — renders a saved chart.
  • Query table — renders a saved query’s rows directly as a table.

Composition is in-place: Edit puts the dashboard in draft mode, Add tile picks a chart or saved query, and tiles are dragged and resized on a 12-column grid (each row unit is about 80px). A tile can override its title; otherwise it shows the underlying chart or query name. Nothing is stored until Save writes the whole draft back — Cancel discards it.

References from tiles to charts and queries are soft: deleting a chart or query doesn’t break the dashboard, its tile just shows “This chart no longer exists” until re-pointed.

Saved query SQL + variables Chart bar · line · area · pie Query table rows as a grid Dashboard tiles on a 12-col grid Home page admin-pinned tiles
Each layer is a separate, reusable object; references between layers are by id and survive edits to the layer below.

A dashboard can declare its own variables, bound by name to the {{placeholder}}s in the SQL behind its tiles: one region control at the top of the dashboard filters every tile whose query references {{region}}. A variable left on “All” is unset, dropping the [[ ... ]] optional blocks that reference it — see template variables. The variables dialog suggests every placeholder name it finds in the tiles’ SQL, copying the definition from the underlying query when one exists. For placeholders a dashboard does not declare, the tile falls back to the underlying query’s own default values.

Tiles fetch their data when the dashboard opens, and re-run automatically when a variable value changes. Each tile also has a manual Refresh button. There is no timed auto-refresh — a dashboard left open on a wall screen shows the numbers from when it loaded until something re-runs it.

API: GET /dashboards, POST /dashboards, PUT /dashboards/{dashboardId}, DELETE /dashboards/{dashboardId}.


The viewer’s — always. A dashboard stores only definitions (which chart, which query, where on the grid). When someone opens it, each tile calls the query engine with that person’s credentials, so:

  • What a viewer sees is exactly what they could get by running the tile’s SQL themselves. The author’s permissions are irrelevant at view time; there is no “run as author” mode and no way for a dashboard to leak data its viewer couldn’t query.
  • Because ad-hoc SQL requires unrestricted record visibility, a viewer whose visibility is restricted on any private table (or by a private field) gets no tile data at all. This shows as a quiet “Not available for your access level.” on each tile rather than an error — deliberate, since a configured page full of red errors reads as breakage.
  • Viewing also requires the ordinary read actions (dashboards:read, charts:read, savedQueries:read) to load the definitions; all three are in every built-in role.

Every member lands on Home. Out of the box it’s a built-in default (quick links to your tables plus the viewer’s recent items). An admin can replace it with a configured home page: the same tile grid as a dashboard, with a wider set of tile kinds — this is how a workspace pins its key dashboardable content as the landing experience.

Editing is in place: the Customize button (shown to holders of customization:manage) opens draft mode seeded with starter tiles matching the default page, so customising feels like taking over the default rather than starting from nothing. Reset to default discards the configuration entirely (DELETE /workspace/homepage).

Tile kinds:

Kind Shows Configuration
chart A saved chart Chart id
table A saved query’s rows as a table Query id
quickLinks A list of in-app links Curated picks, or the built-in permission-aware set
recentRecords The newest records in one table Table id, row count (default 5, max 50)
myRecents The viewer’s own recently visited items None (per-viewer)
markdown A block of admin-authored text Up to 4,000 characters

Notes on the pieces:

  • Quick links name real in-app destinations (a table’s records, sheet or board, a specific dashboard, the builder pages) chosen from a picker — not free-text URLs — so links can’t drift off-product or break with routing changes. Without a label override, a link shows its destination’s live name: rename the table, the link renames itself. In builtIn mode the tile recomputes the same permission-aware link set the default page shows, per viewer. Links to builder pages render only for viewers holding builder:access.
  • Chart and table tiles are the same tiles dashboards use, with the same viewer-permission behaviour: restricted viewers see “Not available for your access level” instead of data — expected, since a home page targets the whole workspace.
  • A page holds up to 40 tiles; a quick-links tile up to 24 curated links.
  • Graceful degradation is built in: a viewer whose role lacks customization:read (or a fetch failure) gets the built-in default page rather than an error, and a tile kind a client doesn’t recognise is skipped, not mangled — old app versions won’t delete a newer tile when they edit.

API: GET /workspace/homepage, PUT /workspace/homepage (full replace of the tile list, validated on write), DELETE /workspace/homepage. Reading is customization:read (all roles); writing is customization:manage (admin-only by default).


The Dashboards page includes an AI dashboard assistant: describe the dashboard you want, and it drafts a complete plan — new saved queries, charts, and the dashboard that arranges them, reusing existing queries and charts where they fit. The SQL in a plan is validated against your workspace’s real tables before you see it, and nothing is created until you press Apply: the plan is then created atomically (everything or nothing) via POST /dashboard-plans/apply, producing ordinary queries, charts, and dashboards you can edit like any other. Plans are additive only — they never modify or delete existing objects. Validating a plan requires only dashboards:read; applying one requires dashboards:manage. See AI assistants.


Q: Can I share a dashboard with just one team, or make one private?

Not currently. All dashboards (and charts, and saved queries) are workspace-visible to anyone with the read action, and editable by anyone with the manage action. What you can control is the data: tiles show each viewer only what their own permissions allow (which for dashboards is all-or-nothing — see above).

Q: A colleague opens my dashboard and every tile says “Not available for your access level”.

Their record visibility is restricted somewhere in the workspace (a private table where their scope is narrower than workspace-wide, or a private field they can’t read), so the query engine refuses to run tiles for them. This is the deliberate all-or-nothing rule for raw SQL — see Queries & exports.

Q: Someone edited a chart and it changed on three dashboards. Expected?

Yes — charts are shared objects referenced by id, so an edit lands everywhere at once. Use Duplicate (on charts and on saved queries) when a change should not propagate; the usage chips show which dashboards a chart feeds before you edit it.

Q: Do dashboards auto-refresh?

No. Tiles load on open and re-run on variable changes or the per-tile Refresh button. There is no polling interval.

Q: Members can edit dashboards but can’t open the Charts page — why?

Dashboards live in the end-user area, gated only by dashboards:manage. The Charts page (and the Query page) are builder surfaces behind builder:access, admin-only by default. Grant a member builder:access through a custom role to let them author charts; composing existing charts into dashboards needs no builder access at all.

Q: Can a home-page tile show a whole dashboard?

Not embedded — chart and table tiles pin individual pieces. To point people at a full dashboard, add a quick link whose target is that dashboard.

Open the app