Dashboards
Compose your own dashboards from a 10-widget library and pin one as the org default. Dashboards are owned by the organization — anyone with the right role sees the same set.
System Presets
Four presets ship out of the box. Presets are read-only — you can clone any preset to create your own dashboard, but the originals never change. Presets are served from memory and are never persisted to the database.
| Preset | Audience | Default widgets |
|---|---|---|
executive | Leadership / FinOps leads | Stat cards, cost trend, top costly resources, recommendations |
engineering | Platform & SRE teams | Schedule execution, upcoming actions, recommendations, cloud spend |
finops | Finance partners | Showback by team, cost trend, budget health, top costly resources |
all_widgets | Everyone | All 10 widgets, useful as a starting point for clones |
Widget library
Every dashboard is a layout over the same 10 widgets. Each widget declares its required policy and is rendered through an error boundary — a widget you can't see, or a widget that throws, becomes a placeholder instead of unmounting the page.
| Widget type | What it shows | Required policy |
|---|---|---|
stat_cards | Compact key-metric tiles (cost, savings, anomalies, resources) | dashboard:view |
cost_trend | Daily/weekly/monthly cost line chart | reports:view |
cloud_spend | Per-provider spend breakdown | reports:view |
top_costly | Top N costly resources | reports:view |
recommendations | Open recommendations + savings | recommendation:view |
quick_insights | Curated callouts (idle/orphan/anomalies) | reports:view |
budget_health | Budget status across teams | reports:view |
showback | Cost attribution by team or tag | reports:view |
schedule_execution | Recent scheduler executions | schedule:view |
upcoming_actions | Next 24h scheduled start/stop actions | schedule:view |
Bounds
| Bound | Limit | On exceed |
|---|---|---|
| Dashboards per org | 50 | 409 — code: DASHBOARD_LIMIT_EXCEEDED |
| Widgets per dashboard | 50 | 400 on save |
| Widget config size | 4 KiB | 400 on save |
| Layout payload size | 64 KiB | 400 on save |
| Name uniqueness | Per-org (active rows) | 409 — code: DUP_NAME |
RBAC
Four policies gate dashboard operations:
dashboard:view— read dashboards and presetsdashboard:create— create new dashboards (counts against the org's 50-dashboard quota)dashboard:update— rename, edit layout, change widgets, set defaultdashboard:delete— delete a user-created dashboard (presets are immutable)
API
List dashboards
/dashboardsList dashboards visible to the caller, plus the org's default-dashboard pointer.
Query: ?limit=20&offset=0&sort_by=name&sort_order=asc
{
"data": [
{ "id": "executive", "name": "Executive", "kind": "preset" },
{ "id": "engineering", "name": "Engineering", "kind": "preset" },
{ "id": "finops", "name": "FinOps", "kind": "preset" },
{ "id": "all_widgets", "name": "All Widgets", "kind": "preset" },
{
"id": "01HF8K9C5G4M2N3P4Q5R6S7T8U",
"name": "Platform Team",
"kind": "user",
"createdAt": "2026-04-26T10:30:00Z",
"updatedAt": "2026-04-27T08:00:00Z"
}
],
"defaultDashboard": "executive"
}Get dashboard
/dashboards/{id}Get a dashboard by id. Preset keys are served from memory; UUIDs hit the dashboards table.
Create dashboard
/dashboardsCreate a new user-owned dashboard. Cloning a preset is a client-side operation: GET the preset, modify, POST.
{
"name": "Platform Team",
"layout": { "rows": [[{ "type": "stat_cards", "size": "wide" }]] },
"widgets": [
{ "type": "stat_cards", "config": {} }
]
}Update dashboard
/dashboards/{id}Partial update — name, layout, or widgets. All-nil bodies return 400. PATCH on a preset id returns 405 (ErrPresetImmutable).
Set default dashboard
/dashboards/defaultSet the org's default dashboard. Pointer lives in org_settings under key default_dashboard.
{ "id": "executive" }Send { "id": "" } to clear the pointer — frontend falls back to all_widgets.
Delete dashboard
/dashboards/{id}Delete a user-owned dashboard. Preset keys return 405. If the deleted dashboard is the org default, the pointer is cleared in the same transaction.
Tenant cascade
See Roles & Permissions for how dashboard policies compose with the rest of the policy table.