dashboard-design
When to use
Use when designing a new Grafana or admin dashboard, deciding what goes where (Grafana vs. app), or embedding Grafana panels in the Laravel app.
Do NOT use when:
- Writing Grafana queries/JSON (use
grafana skill)
- Building Livewire components (use
livewire skill)
Procedure: Design a dashboard
- Inspect the data sources — Identify which signals already exist (logs, metrics, app queries) and where they live (Grafana / Loki / app DB) before designing a new panel.
- Pick the surface — Use the decision tables below to choose Grafana, app dashboard, or embed; document audience and refresh cadence.
- Draft the layout — Sketch panels, choose visualization per signal (RED / USE / Golden Signals), define filters and thresholds.
Ground the chart-type choice in the adopted data-viz corpus instead
of memory:
./scripts-run <skills-root>/corpus-grounding/scripts/ground search --manifest <skills-root>/design-intelligence/data/manifest.json --domain chart "<data shape>" returns the best chart type, when-NOT-to-use, data-volume
threshold, a11y grade + colorblind fallback, and a library
recommendation per row (see
design-intelligence).
- Implement and verify — Build the dashboard, load realistic data, and confirm every panel answers a named question for the named audience.
| Domain |
Technology |
Purpose |
| Monitoring |
Grafana + Loki |
Infrastructure health, error rates, logs, SLAs |
| Business/Admin |
Laravel + Livewire + Tailwind |
Customer KPIs, import stats, usage metrics |
Decision: What goes where?
| Data |
Where |
| Server metrics, error rates, latency |
Grafana |
| Log analysis, traces |
Grafana (Loki) |
| SLA/uptime tracking |
Grafana |
| Customer-facing KPIs |
App dashboard |
| Import statistics per customer |
App dashboard (+ Grafana embed) |
| User activity, usage metrics |
App dashboard |
Grafana Embedding
<iframe
src="https://grafana.example.com/d-solo/{dashboard-uid}/{panel-id}?orgId=1&from=now-24h&to=now&var-fqdn={{ $customer->fqdn }}&theme=light"
width="100%" height="300" frameborder="0"
></iframe>
Config required: allow_embedding = true, cookie_samesite = none (cross-origin), anonymous access/auth proxy, tenant variables via URL params, &theme=light|dark.
| Scenario |
Approach |
| Quick KPI overview |
Embed Grafana stat panels |
| Detailed investigation |
Link to full Grafana dashboard |
| Customer-facing |
Build in app (full UX control) |
Admin Dashboard Design (Laravel)
Widget types
| Widget |
Implementation |
| Stat card |
Livewire + Tailwind |
| Trend card |
Stat + sparkline (Chart.js / Grafana embed) |
| Table widget |
Livewire table with pagination |
| Chart widget |
Chart.js / Grafana embed |
| Status list |
Blade component with color indicators |
| Activity feed |
Livewire with polling/streaming |
Layout: F-pattern
┌──────────┬──────────┬──────────┬──────────┐
│ Stat │ Stat │ Stat │ Stat │ ← KPI row
├──────────┴──────────┼──────────┴──────────┤
│ Chart (trend) │ Chart (breakdown) │ ← Viz row
├─────────────────────┼─────────────────────┤
│ Table (recent) │ Activity feed │ ← Detail row
└─────────────────────┴─────────────────────┘
Livewire patterns
wire:poll.30s for auto-refresh
wire:init for lazy loading expensive queries
$dispatch('refresh-stats') for cross-widget updates
- Cache expensive aggregations, refresh on schedule
Validate
- Verify each panel answers exactly one question.
- Confirm time ranges are explicit, not "last X" without context.
- Check that critical KPIs are visible without scrolling.
- Ensure no chart mixes unrelated metrics on the same axis.
Output format
- Dashboard layout with panel placement and visualization types
- Data source mapping — which metrics/queries feed each panel
- Alerting thresholds where applicable
Gotcha
- Max 8 panels per dashboard — cognitive overload kills usability.
- Simple table often beats fancy visualization.
- Always scope to customer/tenant — no unfiltered admin views.
- Always define time range explicitly.
Do NOT
- Do NOT create dashboards with more than 8 panels — cognitive overload.
- Do NOT mix ops metrics with business KPIs on the same dashboard.
- Do NOT show admin data without tenant scoping.
Anti-slop
Dashboards have their own signature tell: the hero-metric template (giant
number + small label + a row of stats + gradient) is L1 in
docs/guidelines/design-antipatterns.md.
Pull the catalog and check L1–L3 (hero-metric, identical-card grids, monotonous
spacing) before finalizing the layout — a dashboard is product-mode
(docs/guidelines/design-modes.md): design serves the task, so favour data
density and earned familiarity over decorative variance.
Auto-trigger keywords
- dashboard
- monitoring dashboard
- visualization
- KPI
- metrics display
1---2name: dashboard-design3description: Use when designing monitoring dashboards — visualization selection, layout principles, observability strategies (RED/USE/Golden Signals), and data storytelling.4---56# dashboard-design78## When to use910Use when designing a new Grafana or admin dashboard, deciding what goes where (Grafana vs. app), or embedding Grafana panels in the Laravel app.1112Do NOT use when:13- Writing Grafana queries/JSON (use `grafana` skill)14- Building Livewire components (use `livewire` skill)1516## Procedure: Design a dashboard17181. **Inspect the data sources** — Identify which signals already exist (logs, metrics, app queries) and where they live (Grafana / Loki / app DB) before designing a new panel.192. **Pick the surface** — Use the decision tables below to choose Grafana, app dashboard, or embed; document audience and refresh cadence.203. **Draft the layout** — Sketch panels, choose visualization per signal (RED / USE / Golden Signals), define filters and thresholds.21 **Ground the chart-type choice** in the adopted data-viz corpus instead22 of memory: `./scripts-run <skills-root>/corpus-grounding/scripts/ground23 search --manifest24 <skills-root>/design-intelligence/data/manifest.json --domain chart25 "<data shape>"` returns the best chart type, when-NOT-to-use, data-volume26 threshold, a11y grade + colorblind fallback, and a library27 recommendation per row (see28 [`design-intelligence`](../design-intelligence/SKILL.md)).294. **Implement and verify** — Build the dashboard, load realistic data, and confirm every panel answers a named question for the named audience.3031| Domain | Technology | Purpose |32|---|---|---|33| **Monitoring** | Grafana + Loki | Infrastructure health, error rates, logs, SLAs |34| **Business/Admin** | Laravel + Livewire + Tailwind | Customer KPIs, import stats, usage metrics |3536### Decision: What goes where?3738| Data | Where |39|---|---|40| Server metrics, error rates, latency | Grafana |41| Log analysis, traces | Grafana (Loki) |42| SLA/uptime tracking | Grafana |43| Customer-facing KPIs | App dashboard |44| Import statistics per customer | App dashboard (+ Grafana embed) |45| User activity, usage metrics | App dashboard |4647### Grafana Embedding4849```html50<iframe51 src="https://grafana.example.com/d-solo/{dashboard-uid}/{panel-id}?orgId=1&from=now-24h&to=now&var-fqdn={{ $customer->fqdn }}&theme=light"52 width="100%" height="300" frameborder="0"53></iframe>54```5556Config required: `allow_embedding = true`, `cookie_samesite = none` (cross-origin), anonymous access/auth proxy, tenant variables via URL params, `&theme=light|dark`.5758| Scenario | Approach |59|---|---|60| Quick KPI overview | Embed Grafana stat panels |61| Detailed investigation | Link to full Grafana dashboard |62| Customer-facing | Build in app (full UX control) |6364## Admin Dashboard Design (Laravel)6566### Widget types6768| Widget | Implementation |69|---|---|70| Stat card | Livewire + Tailwind |71| Trend card | Stat + sparkline (Chart.js / Grafana embed) |72| Table widget | Livewire table with pagination |73| Chart widget | Chart.js / Grafana embed |74| Status list | Blade component with color indicators |75| Activity feed | Livewire with polling/streaming |7677### Layout: F-pattern7879```80┌──────────┬──────────┬──────────┬──────────┐81│ Stat │ Stat │ Stat │ Stat │ ← KPI row82├──────────┴──────────┼──────────┴──────────┤83│ Chart (trend) │ Chart (breakdown) │ ← Viz row84├─────────────────────┼─────────────────────┤85│ Table (recent) │ Activity feed │ ← Detail row86└─────────────────────┴─────────────────────┘87```8889### Livewire patterns9091- `wire:poll.30s` for auto-refresh92- `wire:init` for lazy loading expensive queries93- `$dispatch('refresh-stats')` for cross-widget updates94- Cache expensive aggregations, refresh on schedule9596### Validate9798- Verify each panel answers exactly one question.99- Confirm time ranges are explicit, not "last X" without context.100- Check that critical KPIs are visible without scrolling.101- Ensure no chart mixes unrelated metrics on the same axis.102103## Output format1041051. Dashboard layout with panel placement and visualization types1062. Data source mapping — which metrics/queries feed each panel1073. Alerting thresholds where applicable108109## Gotcha110111- Max 8 panels per dashboard — cognitive overload kills usability.112- Simple table often beats fancy visualization.113- Always scope to customer/tenant — no unfiltered admin views.114- Always define time range explicitly.115116## Do NOT117118- Do NOT create dashboards with more than 8 panels — cognitive overload.119- Do NOT mix ops metrics with business KPIs on the same dashboard.120- Do NOT show admin data without tenant scoping.121122## Anti-slop123124Dashboards have their own signature tell: the **hero-metric template** (giant125number + small label + a row of stats + gradient) is L1 in126[`docs/guidelines/design-antipatterns.md`](../../../docs/guidelines/design-antipatterns.md).127Pull the catalog and check L1–L3 (hero-metric, identical-card grids, monotonous128spacing) before finalizing the layout — a dashboard is product-mode129(`docs/guidelines/design-modes.md`): design serves the task, so favour data130density and earned familiarity over decorative variance.131132## Auto-trigger keywords133134- dashboard135- monitoring dashboard136- visualization137- KPI138- metrics display