dashboard-beautify-bc8385 — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited dashboard-beautify-bc8385 (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Production-grade dashboards and infographics with Dash and Plotly Python.
Philosophy: form follows function, colour communicates, every design decision earns its place. A dashboard is a curated argument made from data — not a chart dump.
Default target: production delivery. Optimise for correctness, maintainability, and accessibility from the start — not as an afterthought.
If any of these are unanswered, ask before writing code.
Run this before any design work. A beautiful dashboard built on bad data is worse than no dashboard.
Read references/data-quality.md for full checks. Minimum required:
| Data intent | Recommended | Never |
|---|---|---|
| Change over time | Line, area, connected scatter | Bar (unless discrete periods only) |
| Compare categories | Horizontal bar (many labels), column (few) | Line (implies continuity between categories) |
| Part of a whole | Stacked bar, treemap, sunburst | Pie with > 4 slices |
| Distribution | Histogram, violin, box plot | Bar chart of means (hides spread) |
| Correlation / relationship | Scatter, bubble (3rd variable as size) | Line |
| Flow / transfer | Sankey | — |
| Multi-variable dense | Heatmap, parallel coordinates | Radar/spider (angle distorts magnitude) |
| Single KPI | Styled html.Div card — no chart | Any chart type |
| Multiple series, different scales | Small multiples (facets) | Dual-axis (almost always misleading) |
Hard anti-patterns — flag to user unless explicitly overridden:
Read references/chart-selection.md for edge cases and the full decision framework.
Read references/colour-theory.md for the full palette library and per-theme Plotly template code.
This skill is theme-agnostic. Select the appropriate theme for the project and apply it consistently — do not mix themes within a project. Available themes documented in the reference:
Colour rules — apply regardless of theme:
references/colourblindness.md.colours.py module.Read references/layout-principles.md for grid recipes and typography scale.
dbc.Container / dbc.Row / dbc.Col from dash-bootstrap-components for all grid work.dbc.Card with consistent internal padding (p-3)."Revenue grew 34% after the Q2 pricing change" not "Revenue over time".Register a named template once in app.py before the layout import. Every figure inherits it automatically.
Fill palette values from colours.py for the selected theme. Full per-theme template code is in references/colour-theory.md.
import plotly.graph_objects as go
import plotly.io as pio
from colours import PALETTE, SURFACE, TEXT_PRIMARY, TEXT_MUTED, GRID, HOVER_BG, HOVER_BORDER
pio.templates["project_theme"] = go.layout.Template(
layout=go.Layout(
font=dict(family="Inter, system-ui, sans-serif", size=13, color=TEXT_PRIMARY),
paper_bgcolor="rgba(0,0,0,0)", # transparent — card handles background
plot_bgcolor=SURFACE,
colorway=PALETTE,
margin=dict(l=40, r=20, t=55, b=40),
title=dict(
font=dict(size=16), # use html.B() in title string for bold — weight is not a valid Plotly font property
x=0.0,
xanchor="left",
),
xaxis=dict(gridcolor=GRID, linecolor=GRID,
tickfont=dict(size=11, color=TEXT_MUTED), zeroline=False),
yaxis=dict(gridcolor=GRID, linecolor=GRID,
tickfont=dict(size=11, color=TEXT_MUTED), zeroline=False),
legend=dict(orientation="h", y=1.02, x=0,
bgcolor="rgba(0,0,0,0)", borderwidth=0),
hoverlabel=dict(bgcolor=HOVER_BG, bordercolor=HOVER_BORDER,
font=dict(size=12, color=TEXT_PRIMARY)),
)
)
pio.templates.default = "project_theme"Chart functions live in components/charts.py and are pure: DataFrame in, go.Figure out — no side effects, no globals, no Dash logic inside figure functions.
project/
├── app.py # Dash init, template registration, server export
├── layout.py # Full app layout
├── callbacks.py # All @callback functions
├── colours.py # Single source of truth for all colour constants
├── components/
│ ├── charts.py # Pure figure-building functions
│ └── cards.py # KPI cards and reusable UI components
├── data/
│ └── loader.py # Data loading, preprocessing, caching
└── assets/
└── custom.css # Minimal overrides onlyRead references/performance.md before building against real data at scale. Minimum requirements:
functools.lru_cache)go.Scattergl, go.Heatmapgl) for > 10k data pointsdcc.Loading wrapper on every chart that involves a data fetch callbackRead references/interaction-design.md for full rules. Core principles:
dcc.Store for shared state — never global Python variables in callbacks.dash.no_update for unchanged outputs.Read references/formatting.md for full conventions. Non-negotiable defaults:
DD Mon YYYY (e.g. 15 Jan 2024) — never ambiguous MM/DD/YY£4.2M)68.3%)formatting.pyAll boxes must be checked before release.
Data correctness
□ Key metrics reconciled against source of truth
□ Filters tested for empty results — empty state handled gracefully
□ Date range edge cases tested (first day, last day, single day)
□ Aggregations spot-checked against raw data for a known sampleVisual and UX
□ Primary question answered in < 3 seconds on default view
□ Chart titles state the insight, not the chart type
□ Axis labels include units where not obvious from context
□ hovertemplate set on all traces (value + label + unit)
□ Consistent chart heights within each row
□ Filters positioned above the charts they affect
□ Empty-state message shown when a filter returns no data
□ Layout checked at 375px mobile viewport widthAccessibility
□ Colour is not the only encoding for any critical distinction
□ Red/green signal pairs have redundant encoding (shape / dash / pattern)
□ WCAG AA contrast met for all text (4.5:1 normal, 3:1 large/bold)
□ config={"responsive": True} on all dcc.Graph components
□ Tab order is logical — filters before charts, charts in reading order
□ Key chart insights have a visible text summary (not hover-only)
□ Simulated under deuteranopia — no information is lostCode quality
□ No hex colour literals inline — all colours imported from colours.py
□ All chart functions are pure (DataFrame in, Figure out)
□ No global mutable state in callbacks
□ dcc.Loading on all data-fetch callbacks
□ weight not used in any Plotly font dict| File | When to read |
|---|---|
references/chart-selection.md | Choosing chart type, edge cases, anti-patterns |
references/colour-theory.md | Theme selection, full palette library, per-theme template code |
references/colourblindness.md | CVD simulation, redundant encoding, contrast checking, keyboard/screen-reader |
references/layout-principles.md | Grid recipes, typography scale, infographic anatomy |
references/data-quality.md | Pre-design data checks, missingness, outliers, metric definitions |
references/performance.md | Large data, WebGL, caching, callback memoization |
references/interaction-design.md | Filter rules, drill-down vs cross-filter, control count limits |
references/formatting.md | Dates, timezones, currency, number abbreviation conventions |
references/observability.md | Structured logging, callback timing, error handling patterns |
references/testing.md | Figure function tests, callback integration tests, snapshot regression |
references/validation.md | Pre-ship QA checklist, value reconciliation, axis/unit sanity checks |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.