single-file-dashboard
Skill17 starsChanged 56 days agoMITView on GitHub
Build single-file zero-dependency interactive HTML dashboards for analytical artifacts that must be emailable, offline-viewable, or airgap-safe. Inline vanilla-SVG charts, no CDN, no remote scripts, no web fonts, no images. Useful for client deliverables, security audit reports, executive dashboards, post-mortems, technology consolidation analyses, and anything that needs to render identically in a browser, an email client, an airgapped laptop, or a regulator review. Use when the user asks for a "dashboard", "interactive HTML report", "shareable analysis", "offline dashboard", "airgap-safe report", or wants to turn an analytical workbook / dataset into a presentable HTML view.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- 1231Johnny/claude-skillstheir own version, first seen Sep 25, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- 1231Johnny/claude-skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository53 other files it gives its agents.
- agents-sdkSkill
- agent-workflowSkill
- api-designSkill
- aws-iamSkill
- bash-shell-scriptingSkill
- cicd-github-actionsSkill
- cloudflare-email-serviceSkill
- cloudflareSkill
- cloudflare-waf-authorSkill
- cloudflare-workers-authorSkill
- cloud-platformsSkill
- codebase-security-auditSkill
- containers-orchestrationSkill
- core-engineeringSkill
- database-postgresqlSkill
- databricksSkill
- data-engineeringSkill
- distributed-transactionsSkill
- documentation-standardsSkill
- domain-driven-designSkill
- durable-objectsSkill
- frontend-engineeringSkill
- git-workflowSkill
- go-rust-systemsSkill
- iam-security-advisorSkill
- independent-verificationSkill
- infrastructure-iacSkill
- kubernetes-containersSkill
- kubernetes-operator-developmentSkill
- mcp-developmentSkill
- memory-architectureSkill
- multi-perspective-reviewSkill
- networking-transportSkill
- observabilitySkill
- oktaSkill
- pdf-exportSkill
- python-developmentSkill
- reactflow-architecture-diagramsSkill
- sandbox-sdkSkill
- scripting-automationSkill
- security-testingSkill
- service-resilienceSkill
- skills-compositionSkill
- skills-continuous-improvementSkill
- snowflakeSkill
- system-designSkill
- typescript-javascriptSkill
- web-perfSkill
- web-research-kb-refreshSkill
- workers-best-practicesSkill
- workload-identitySkill
- wranglerSkill
- zero-trustSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 8 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 20
Use when the user asks for:
- Distinctive: line 28
Do *not* use for:
- Distinctive: line 39
One file. Zero dependencies: No CDN, no remote scripts, no web fonts, no images.
- Very specific: line 40
Inline vanilla SVG for charts: No D3, Chart.js, ECharts, or React.
- Distinctive: line 41
Escape user content: Every string pulled from data must be HTML-escaped.
- Distinctive: line 42
Renders identically offline: Test by disabling network.
- Distinctive: line 44
Re-runnable, not editable: Never edit generated HTML.
- Distinctive: line 249
Keep interactivity minimal and offline-friendly:
- Distinctive: line 257
Do not implement: drag-and-drop, infinite scroll, persistence (localStorage is fine.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Single-File Dashboard
How to ship analytical artifacts as single-file, fully self-contained, zero-dependency HTML dashboards that render identically online, offline, on an airgapped laptop, and inside an email client.
Companion rules:
800-markdown.mdc- markdown formatting for prose deliverables810-documentation.mdc- documentation patterns815-reactflow-diagrams.mdc- interactive React Flow canvases (the other dashboard pattern; see contrast below)
When to invoke
Use when the user asks for:
- "Build a dashboard" / "interactive HTML report" / "shareable analysis"
- "Offline dashboard" / "airgap-safe" / "for the client" / "for the regulator"
- "Visualize this workbook" / "turn this CSV into a presentable view"
- An executive-style deliverable for client / leadership / regulator review
- Anything that must render without internet access
Do not use for:
- React applications (use a real frontend stack)
- Embedded analytics inside a webapp (use a charting library and your build pipeline)
- Real-time / streaming dashboards (use Grafana / Datadog / Looker)
- Interactive architecture canvases with custom nodes / edges - use
815-reactflow-diagrams.mdcand the React Flow skill instead
The Six Golden Rules
- One file. Zero dependencies. No CDN, no remote scripts, no web fonts, no images. Inlined CSS, inlined JS, inlined data, inlined SVG.
- Inline vanilla SVG for charts. No D3, Chart.js, ECharts, or React. Vanilla SVG renders everywhere; libraries do not.
- Escape user content. Every string pulled from data must be HTML-escaped. Never bypass.
- Renders identically offline. Test by disabling network; the dashboard must look unchanged.
- Renders identically in email. Open the file in Gmail / Outlook / Apple Mail (as an attachment); layout must hold.
- Re-runnable, not editable. Never edit generated HTML. Edit the generator and re-run.
When to choose this pattern vs alternatives
| Need | Use this skill | Use React Flow | Use real BI tool | Use Markdown |
| Client / executive deliverable; must be emailable | yes | no | no | maybe |
| Airgap / regulated environment | yes | possibly (still SPA) | no | yes |
| Interactive architecture canvas with custom nodes | no | yes | no | no |
| Real-time / streaming data | no | no | yes | no |
| Analytical workbook -> shareable HTML | yes | no | maybe | no |
| Live KPIs across many sources | no | no | yes | no |
| Static narrative document | no | no | no | yes |
Architecture
+--------------------------+
| Source artifact |
| (xlsx / csv / json / |
| parquet / api dump) |
+----------+---------------+
|
v
+--------------------------+
| Build script (Python) |
| - parse source |
| - shape model |
| - render HTML shell |
| - inline CSS, JS, SVG |
| - inline data as JSON |
| in <script> tags |
+----------+---------------+
|
v
+--------------------------+
| Single-file HTML output |
| - no external requests |
| - opens with file:// |
+--------------------------+The build script is the source of truth. The HTML is the artifact.
Workflow
- Locate the source. Excel workbook, CSV, JSON dump, parquet - whatever the upstream produced. If multiple candidates exist, ask the user.
- Define the dashboard sections. Typical executive layout:
- Overview (KPIs + thesis sentence)
- Key decisions / findings
- Charts (1-3 per section, never more)
- Detail tables (sortable / filterable)
- Risks / next steps
- Methodology / source links
Run the generator.
python3 build_dashboard.py --source <input>.xlsx --output <output>.html- Verify offline. Disable network; reload in browser. Anything that breaks (missing font, blank chart) violates the zero-dep guarantee.
- Verify in email client. Save and reopen as an attachment in Gmail / Outlook. Layout must hold.
- Report back. Summarize counts (sections rendered, items per section, charts), the absolute output path, and a
open <path>command for macOS.
Design system (executive palette)
A consistent design system makes outputs presentable without manual adjustment.
Palette
| Token | Hex | Use |
| navy | #051C2C | Headlines, top rule, hero |
| slate | #54758C | Secondary text, axis labels |
| line | #E1E6EB | Borders, gridlines |
| accent blue | #2251FF | Primary action, links, key bars |
| positive green | #0F6E3E | Positive deltas, "what worked" callouts, retain decisions |
| negative red | #B33A3A | Negative deltas, "horror story" callouts, decommission decisions |
| warning amber | #C18100 | Cautionary emphasis, contested decisions |
| neutral grey | #6B7280 | Disabled / N/A states |
Typography
- System sans only (Inter / SF / Segoe UI / Helvetica). No web fonts.
- Display 44px / Headline 28px / Subhead 20px / Body 15px / Caption 12px.
- All-caps 11px eyebrows with wide letter-spacing for section labels.
- Tabular nums for all numeric tables.
Layout
- 1320px container, 56px gutters, 72px band padding.
- Top sticky nav (anchor links to sections).
- Horizontal-rule section dividers (no boxed cards everywhere).
- Tables: navy top rule, sticky headers, hover row highlight, no vertical gridlines.
Chips & callouts
Standard chip styles for repeated semantics (decisions, severities, deltas, advantages):
<span class="chip chip--retain">RETAIN</span>
<span class="chip chip--phase-out">PHASE OUT</span>
<span class="chip chip--severity-high">HIGH</span>
<span class="chip chip--shift-up">+0.42 vs balanced</span>Green / amber / red callouts for evidence pairs (e.g., what-worked / horror-story from the multi-perspective-review skill).
Charts (vanilla SVG)
The discipline that distinguishes this skill from "throw in a Chart.js script tag". Implement a small set of charts in pure SVG so the output never reaches for the network.
Chart inventory (cover 90% of executive dashboards)
| Chart | Use |
| Horizontal bar | Decision mix, score comparison, ranked items |
| Vertical bar | Period comparison, category counts |
| Multi-series line | KPIs over time, success metrics |
| Gantt | Roadmap, phase plan |
| Stacked bar | Composition over time, mix shifts |
| Donut / pie | Avoid in executive dashboards; use horizontal bar instead |
Skeleton
// Vanilla SVG bar chart helper - inline in the dashboard, no imports.
function svgEl(name, attrs) {
const el = document.createElementNS('http://www.w3.org/2000/svg', name);
for (const [k, v] of Object.entries(attrs)) el.setAttribute(k, v);
return el;
}
function renderHbar(containerId, data, opts = {}) {
const c = document.getElementById(containerId);
const w = c.clientWidth, barH = opts.barH ?? 24, pad = 12;
const max = Math.max(...data.map(d => d.value));
const labelW = opts.labelW ?? 200;
const svg = svgEl('svg', { width: w, height: data.length * (barH + pad) + pad });
data.forEach((d, i) => {
const y = pad + i * (barH + pad);
svg.appendChild(svgEl('text', {
x: 0, y: y + barH * 0.7, fill: 'var(--slate)',
'font-size': '13', 'font-family': 'inherit',
})).textContent = d.label;
const barW = ((w - labelW - 60) * d.value) / max;
svg.appendChild(svgEl('rect', {
x: labelW, y, width: barW, height: barH,
fill: opts.fill ?? 'var(--accent-blue)',
}));
svg.appendChild(svgEl('text', {
x: labelW + barW + 6, y: y + barH * 0.7, fill: 'var(--navy)',
'font-size': '13', 'font-family': 'inherit',
'font-variant-numeric': 'tabular-nums',
})).textContent = d.value.toLocaleString();
});
c.appendChild(svg);
}
window.addEventListener('resize', () => {
document.querySelectorAll('[data-chart]').forEach(el => {
el.innerHTML = '';
renderChart(el.id); // user-supplied dispatcher
});
});Embedding the data
Inline as JSON in <script type="application/json"> tags. Parse on init.
<script type="application/json" id="decisionMixData">
[
{"label": "Retain", "value": 7},
{"label": "Retain (Scoped)", "value": 3},
{"label": "Phase out", "value": 2},
{"label": "Decommission", "value": 1}
]
</script>
<div id="decisionMixChart" data-chart="hbar"></div>
<script>
const data = JSON.parse(document.getElementById('decisionMixData').textContent);
renderHbar('decisionMixChart', data);
</script>The chart renders from JSON in the same file. No fetch. No network.
Tooltips and interactions
Keep interactivity minimal and offline-friendly:
- Hover tooltip - one shared dark tooltip (custom div positioned at cursor); no library.
- Click filters - filter chips that show/hide rows in tables; pure CSS classes toggled with one event handler.
- Sortable tables - small
<th>click handler that re-renders rows from the inlined JSON. - Section nav - anchor links with smooth-scroll behavior via CSS.
- No router - URL fragments only.
Do not implement: drag-and-drop, infinite scroll, persistence (localStorage is fine; no backend).
Build script structure (Python)
# build_dashboard.py
from pathlib import Path
import argparse
import html
import json
PALETTE = {
"navy": "#051C2C", "slate": "#54758C", "line": "#E1E6EB",
"accent_blue": "#2251FF", "positive": "#0F6E3E",
"negative": "#B33A3A", "warning": "#C18100", "neutral": "#6B7280",
}
HTML_SHELL = """<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>__TITLE__</title>
<style>
:root {
--navy: __NAVY__;
--slate: __SLATE__;
/* ... */
}
body { margin: 0; font-family: Inter, system-ui, sans-serif; color: var(--navy); }
/* ... full CSS inlined here ... */
</style>
</head>
<body>
<nav class="topnav">__NAV__</nav>
<main>
__OVERVIEW__
__DECISIONS__
__CHARTS__
__DETAILS__
__RATIONALE__
</main>
<script>
__JS__
</script>
</body>
</html>
"""
def render(source: Path, output: Path) -> None:
data = parse_source(source)
body = HTML_SHELL
body = body.replace("__TITLE__", html.escape(data["title"]))
for k, v in PALETTE.items():
body = body.replace(f"__{k.upper()}__", v)
body = body.replace("__OVERVIEW__", render_overview(data))
body = body.replace("__DECISIONS__", render_decisions(data))
body = body.replace("__CHARTS__", render_charts(data))
body = body.replace("__JS__", JS_HELPERS)
output.write_text(body, encoding="utf-8")
def render_overview(data):
# All user content goes through html.escape()
thesis = html.escape(data["thesis"])
return f'<section><h1>{thesis}</h1></section>'
JS_HELPERS = """
function svgEl(name, attrs) { /* ... */ }
function renderHbar(id, data, opts) { /* ... */ }
"""
if __name__ == "__main__":
p = argparse.ArgumentParser()
p.add_argument("--source", required=True, type=Path)
p.add_argument("--output", type=Path)
a = p.parse_args()
render(a.source, a.output or a.source.with_suffix(".html"))The script writes a single string to disk. Test it by opening the output in a browser with the network disabled.
Anti-patterns
- Linking to a CDN for any asset. The dashboard breaks on airgap and in email; the guarantee is gone.
- Web fonts (Google Fonts, Adobe Fonts). Falls back to system fonts in email anyway; just use system fonts.
- External images (logos hosted on a CDN). Either inline as base64 SVG or omit.
- Charting library (D3, Chart.js, ECharts, Plotly). Each adds 100-500KB and requires either a bundler or a CDN. Vanilla SVG is enough for executive charts.
- Generated HTML edited in place. Make changes in the generator and re-run; otherwise the artifact and the source diverge.
- No HTML escaping. A user-supplied product name with
<script>in it becomes XSS in the dashboard. - Donut / 3D / sunburst charts. Hard to read at executive density. Use bar charts.
- More than 3 charts in a single section. Cognitive load over signal.
- Localizing into the HTML ("English en", "French fr") - use one language per output; multiple outputs for multiple languages.
Testing checklist
- Open with network disabled; everything renders
- Open in Gmail / Outlook attachment view; layout holds
- Open in Safari / Chrome / Firefox / Edge; layout holds
- User-supplied strings with
<,>,&,",'render as text, not HTML - Charts re-render correctly on window resize
- Sticky nav remains usable when scrolling
- Sortable tables sort correctly on every column
- Filter chips show/hide expected rows
- Print preview (Cmd-P) produces a usable PDF
- File size under 2 MB (data + chrome). If over, paginate or shrink the data.
Distribution
- Email - attach. The recipient opens locally; no server.
- Shared drive - drop the HTML next to the source workbook.
- Wiki / SharePoint - upload as an attachment, not as a page (preserves the single-file guarantee).
- GitHub Pages - works, but the airgap-safe property is moot; consider a real SPA if you need GitHub Pages anyway.
- Pinning a snapshot - rename to
<analysis>-<YYYYMMDD>.htmlso the artifact is self-dating.
Related
- Rule:
800-markdown.mdc- markdown formatting for non-HTML deliverables - Rule:
810-documentation.mdc- documentation patterns - Rule:
815-reactflow-diagrams.mdc- interactive React Flow canvases (different niche; SPA, not single-file) - Skill:
multi-perspective-review- panel review whose output renders cleanly into the Advisory section of this dashboard - Skill:
documentation-standards- companion patterns for narrative documentation
Attribution
Pattern crystallized from an executive-style consolidation dashboard generator that produces single-file HTML output (no CDN, no fonts, no images, inline vanilla SVG) sized at <2 MB and renders identically in Chrome, Outlook, and on an airgapped laptop. The single-file/zero-dependency guarantee is the feature.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

