BI Dashboards skill for Claude Code
One definition per number, one owner per dashboard. Claude writes a dashboard brief and a metric register before any chart, then puts definitions in the tool's semantic layer: Metabase models, Superset dataset metrics, Power BI DAX measures or LookML. Layout runs from headline KPIs to trends, breakdowns and detail, row-level security is tested per role, refresh follows the pipeline, and headline numbers are reconciled against a trusted source.
- name
bi-dashboards - size148 lines · ≈1,800 tokens
- files1
- licenseMIT
- updated
What Claude sees before loading it
This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.
description: Builds and governs BI dashboards in Metabase, Looker Studio, Apache Superset, and Power BI - written metric definitions before charts, a semantic layer (Metabase models and metrics, Superset datasets, Power BI DAX measures over a star schema, LookML), dashboard layout from question to KPI to breakdown to detail, filters and drill-through, row-level security, refresh and caching strategy, certification and ownership, and retiring stale content. Use when creating a business dashboard, numbers differ across dashboards, a dashboard is slow, setting up self-serve BI, or cleaning up a sprawling BI workspace. Try asking
- Build a weekly revenue dashboard in Metabase for the sales leadership
- Our two Power BI reports show different active customer counts - fix it
- Clean up our Superset workspace with 400 dashboards nobody owns
Use it when
- Creating a business dashboard in a BI tool
- The same metric shows different values in different places
- A dashboard is slow or shows mixed data freshness
- Setting up governance, certification, or row-level security in BI
Skip it when
- You are building a dashboard UI inside your own product - use dashboard-ui
- You want a custom Python data app - use streamlit-apps
How to check the result
Headline KPIs reconcile with the trusted source for two closed periods, every filter and RLS role is tested with view-as, and load time is measured at default settings.
The common mistake it prevents
Averaging row-level ratios or summing distinct counts in a totals row, which produces numbers that never match the finance team's figures.
A dashboard is done when each number on it traces to one written, owned metric definition, the layout answers a stated question in the order people ask it, filters and permissions behave predictably, it loads in a few seconds, and someone is accountable for it. Charts come last.
Workflow
- [ ] 1. Write the dashboard brief: audience, decisions, questions, cadence
- [ ] 2. Define each metric in the metric register
- [ ] 3. Build or reuse a governed dataset / semantic model
- [ ] 4. Lay out: headline KPIs, trends, breakdowns, detail
- [ ] 5. Add filters, drill paths, and row-level security
- [ ] 6. Set refresh/caching; test load time
- [ ] 7. Validate numbers against a trusted source; certify; assign owner
1. Brief
**Dashboard:** Weekly revenue health **Owner:** finance-analytics (Dana)
**Audience:** VP Sales, regional leads **Cadence:** Monday review, data as of Sunday 23:59 UTC
**Decisions:** where to shift sales capacity; which regions need pricing review
**Questions:** Are we on plan this quarter? Which regions/segments are behind? Is it volume or price?
**Out of scope:** pipeline forecasting (separate dashboard)
If the requester cannot name a decision the dashboard supports, propose a one-off analysis instead of a permanent dashboard.
2. Metric register
| Metric | Definition | Grain / source | Filters baked in | Owner |
|---|---|---|---|---|
| Net revenue | sum(net_amount) of invoices, excluding tax, after refunds, in USD at invoice-date rate | fact_invoice_line | status in (paid, partially_refunded) | Finance |
| Active customers | distinct customers with >= 1 paid invoice in the period | fact_invoice | - | Finance |
| ARPA | net revenue / active customers, same period | derived | - | Finance |
Rules:
- Ratios are computed as
sum(numerator) / sum(denominator)at the displayed level, never as an average of row-level ratios. - State the time attribution (invoice date vs payment date vs order date) and time zone.
- Define once in the semantic layer; dashboards reference the definition, not copy SQL.
- When two teams use the same name for different things, rename one (“bookings” vs “recognized revenue”) instead of tolerating ambiguity.
3. Semantic layer per tool
| Tool | Where definitions live | Notes |
|---|---|---|
| Metabase | Models (curated queries with column metadata) and Metrics; questions built on models | verify/certify models; keep raw tables hidden from casual users |
| Superset | Datasets (physical or virtual) with metrics and calculated columns | define metrics on the dataset, not in each chart; cache per dataset |
| Power BI | semantic model: star schema in Power Query + DAX measures | one shared semantic model, thin report files on top |
| Looker Studio | data source with calculated fields; ideally a prepared BigQuery view | blended sources are fragile and slow - pre-join in the warehouse |
| Looker | LookML views and explores | measures defined in LookML, versioned in git |
Push heavy logic into the warehouse (dbt models or views) and keep BI-layer logic to measures and formatting. Model the source as a star schema (see dimensional-modeling).
Power BI measure examples:
Net Revenue := SUM ( fact_invoice_line[net_amount] )
Active Customers := DISTINCTCOUNT ( fact_invoice[customer_key] )
ARPA := DIVIDE ( [Net Revenue], [Active Customers] )
Net Revenue PY := CALCULATE ( [Net Revenue], SAMEPERIODLASTYEAR ( dim_date[date] ) )
Use measures, not calculated columns, for aggregations; mark dim_date as the date table;
relationships single-direction from dimension to fact unless there is a proven need.
4. Layout
Read order is top-left to bottom-right; place by question priority:
- Headline row: 3-5 KPI tiles - value, comparison (vs plan / prior period), and sparkline. Label the period explicitly (“QTD through Oct 19”).
- Trend: the primary metric over time with target line.
- Breakdowns: by the dimensions in the brief (region, segment), sorted by value or by gap to plan, not alphabetically.
- Detail: a table for drill-down, paginated, with export.
Rules: one question per chart; consistent colors for the same category across charts; no more than ~10-12 charts per page (split into tabs/pages beyond that); show “data as of” timestamp; annotate known incidents (tracking outage, price change). Chart choice and encoding follow data-visualization.
5. Filters, drill, security
- Global filters (date range, region) at the top; show which charts each filter affects. Default the date filter to the period in the brief.
- Cross-filtering and drill-through (Power BI drillthrough pages, Superset drill to detail, Metabase click behavior) beat duplicating charts per segment.
- Row-level security in the tool (Power BI RLS roles with DAX filters, Superset RLS filters, Metabase data sandboxes, Looker access filters) or in the warehouse via authorized views. Test with “view as” for at least two roles.
- Never rely on hiding a filter or a page as a security control.
6. Performance and refresh
| Symptom | Fix |
|---|---|
| Every chart runs a heavy query on open | pre-aggregate in the warehouse (daily summary table), cache results |
| Looker Studio slow on blends | replace blends with a warehouse view; use extracts for small data |
| Power BI DirectQuery slow | import mode with scheduled refresh, or aggregations tables |
| Dashboard shows mixed freshness | align refresh schedules to the upstream pipeline completion |
Target: under 5 s to first meaningful paint for common filters. Schedule refresh after the pipeline that feeds it, not on a fixed clock that races it.
7. Governance
- Certify (verified/endorsed badge) only dashboards whose metrics come from the register.
- Each dashboard has an owner, a description with the brief, and a “last validated” date.
- Organize by domain folders with a clear “certified” vs “sandbox” split.
- Retire content: list dashboards with no views in 90 days (usage analytics in each tool), notify owners, archive after confirmation rather than deleting.
- Version where possible: LookML and Power BI projects (PBIP) in git, Superset and Metabase exports/serialization for promotion between environments.
Gotchas
- Distinct counts do not add up across rows; a “total” row summing distinct customers per region overstates the company total.
- Timezone mismatch between warehouse (UTC) and tool settings shifts daily numbers near midnight.
- Default aggregation guesses (Looker Studio, Superset) sum IDs or average averages; set aggregation explicitly on every field.
- Partial current period plotted next to full periods looks like a drop; mark or exclude it.
- Filters on a dimension with a Type 2 history join can restate the past; decide whether reports show attributes as-of-event or current.
Verification
- Reconcile each headline KPI against the trusted source (finance close, billing system) for two closed periods; record the difference and explanation.
- Test every filter combination in the brief and each RLS role via “view as”.
- Load time measured for default and heaviest filter settings.
- Metric register entries linked from the dashboard description.
About this skill
Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.