Skip to content

walm00/local-dashboard-builder

Repository files navigation

local-dashboard-builder

Turn any repo into a decision dashboard — in an afternoon, with zero dependencies.

A Claude plugin that walks you through a manifest-tracked 7-phase workflow (purpose → data discovery → collectors → UI → scaffold → smoke test → handoff) and drops a working Python-stdlib dashboard into your codebase. No pip install, no framework, no bundler. Decisions first, data second.

license: MIT stdlib only Claude plugin


See it

examples/minimal — every panel kind, fake data, runs on port 8765:

minimal dashboard — all seven panel kinds

examples/engagements — realistic portfolio-tracking dashboard with severity cascades, stacked-bar revenue timeline, Kanban-by-phase active grid, and a live SQLite event log (storage.py demo). Runs on port 8766:

engagements dashboard — portfolio-tracking with severity cascades

Both examples boot with python run.py. No install step. They ship with completed dashboard-manifest.md files so you can read the full 7-phase record of how they were built.


Install

Option A — as a Claude Code plugin (recommended for ongoing use):

/plugin add https://github.com/walm00/local-dashboard-builder

Claude Code reads .claude-plugin/plugin.json, auto-discovers the skill, and makes it available in every repo you work in. Updates are managed by Claude Code's plugin manager.

Option B — install into a specific repo:

# One-liner (from your target repo):
curl -fsSL https://raw.githubusercontent.com/walm00/local-dashboard-builder/main/install.sh | bash

# Or clone and run:
git clone https://github.com/walm00/local-dashboard-builder /tmp/ldb
cd /path/to/your/repo
python /tmp/ldb/install.py

The installer copies skills/local-dashboard-builder/, .claude-plugin/plugin.json, and .claude/scripts/local-dashboard-builder-update.py into your repo. The updater is prefix-named so it coexists cleanly with other Claude Code plugins that also ship an update.py. Safe to re-run — existing files are never overwritten. Python 3.8+ required; no pip install.

Update

If you installed via Option B and want to pull a newer release:

python .claude/scripts/local-dashboard-builder-update.py              # interactive, shows diff
python .claude/scripts/local-dashboard-builder-update.py --dry-run    # preview only
python .claude/scripts/local-dashboard-builder-update.py --yes        # apply without prompt
python .claude/scripts/local-dashboard-builder-update.py --tag v0.3.0 # pin to a specific release

The update script replaces only framework files (skills/local-dashboard-builder/, .claude-plugin/plugin.json, and itself at .claude/scripts/local-dashboard-builder-update.py). Your scaffolded dashboards and filled manifests are never touched. Another plugin's update.py sitting next to it in .claude/scripts/ is left alone — the prefix keeps them from colliding.

Plugin-install users (Option A) get updates from Claude Code automatically.

Build your own dashboard

python skills/local-dashboard-builder/scripts/scaffold.py \
    --name <subject> \
    --target <path-to-repo> \
    [--port 8765] \
    [--data-source empty|csv|sqlite|git|subprocess|filesystem] \
    [--chart-library none|echarts] \
    [--owns-pipeline]

Creates <target>/.claude/scripts/<subject>_dashboard/ with the template files copied over plus a blank dashboard-manifest.md. Fill the manifest phase by phase (WHY first), wire collectors + panels, and run.

Flags:

  • --owns-pipeline — drops schema.sql, scanner.py, and data/.gitignore for a self-contained dashboard that owns its own SQLite pipeline.
  • --chart-library echarts — vendors download_echarts.py alongside the dashboard and wires <script src="/static/vendor/echarts.min.js"> into the HTML. Run python download_echarts.py once after scaffolding to fetch a pinned ECharts build (no npm, no CDN at runtime). Unlocks the scatter and heatmap panel kinds. Default is none (stdlib SVG renderers only).

Validate your manifest

Every dashboard's dashboard-manifest.md carries a schema version. Run the validator any time to confirm the manifest is well-formed for the current phase:

python skills/local-dashboard-builder/scripts/validate.py \
    .claude/scripts/<subject>_dashboard/dashboard-manifest.md

Exit 0 = OK; exit 1 = gate failure with a specific field name. Both example dashboards validate cleanly out of the box.

The workflow

Every dashboard is tracked against a dashboard-manifest.md that the skill refuses to let you skip:

  1. Purpose / WHY — what question, who reads it, what decisions it triggers
  2. Repo Discovery — data inventory, source-to-decision mapping
  3. Collectors — one row per panel: name | source | ttl | severity_rule
  4. UI Mappingid | title | kind | collector | span | ttl | severity | number
  5. Scaffold & Wire — paths, port, run command
  6. Test / Smoke — 8-check results (launch, endpoints, TTL persistence, panel isolation, offline)
  7. Handoff — sign-off checklist

Three gates fire during the workflow:

  • Purpose Alignment (Phase 1) — refuses to discover data until you've written down the decisions the dashboard must trigger.
  • Approach Alignment (Phase 4) — purpose ↔ panels sanity check before a line of code is scaffolded.
  • Smoke Passed (Phase 6) — blocks handoff until 8 smoke checks pass.

Failing a gate bounces you back to the relevant phase with an iteration log entry.

See skills/local-dashboard-builder/references/planning-workflow.md for the full per-phase gate and done-criteria reference.

Panel kinds

Nine kinds ship in the box — each with a documented JSON contract (references/data-contract.md) and a matching renderer in dashboard.js:

Kind Good for Chart library?
metric single-number KPIs, stat strips stdlib
list ranked items, outstanding money, per-row severity stdlib
table tabular rows with columns + alignment stdlib
grid Kanban-style cards, status-by-phase stdlib
progress goal tracking (cash, completion %) stdlib
feed time-ordered events, sweeps, activity log stdlib
chart line / bar / stacked-bar trends, TTL-cached stdlib (SVG)
scatter two-axis distributions, correlations ECharts
heatmap calendar / matrix intensities ECharts

scatter and heatmap require --chart-library echarts at scaffold time. Everything else renders with plain SVG — no pip, no runtime CDN.

Patterns baked into the template

  • Progressive disclosure via a drawer. Any list/grid/table row that includes a _drawer_key in its payload becomes clickable — the template auto-wires a detail drawer. Register a renderBody(item, panel, allData) callback on window.DASHBOARD_DRAWER to customise the drawer per key; no per-dashboard boilerplate.
  • URL-driven filters. Panels can read ?range=Q2 (or any query-string parameter) on each refresh. Pair with a controls= block on serve() to render filter chips that update the URL and trigger re-fetches. The engagements example ships period-slicing chips (YTD / Q2 / 90d / all) that filter the revenue timeline.
  • Typed error envelopes. When a collector fails, _error_envelope() returns a structured payload with an optional hint field; the panel renders a muted error card instead of a raw stack trace. One broken panel never breaks the rest of the grid.
  • Empty-envelope pattern. Collectors can return {"missing": true, "missing_message": "..."} to render a "no data yet" state cleanly — used automatically by ECharts-backed panels when the library isn't vendored.
  • Severity cascade. Per-row or per-collector severity bubbles up to a header badge (ok / warn / critical). CVD-safe palette — tested against Deuteranopia / Protanopia / Tritanopia so the severities stay distinguishable for colour-blind readers.
  • TTL caching + per-panel error isolation. server.py caches each collector's result for its declared TTL and catches exceptions at the panel boundary.

Read references/design-principles.md for the full pattern catalog.

Why

A dashboard is a decision tool, not a data dump. Phase 1 refuses to discover data until you've written down what decisions the dashboard must trigger. Every downstream phase derives from that.

Tech stack is Python stdlib only — no pip install, no framework, no bundler. Any machine that can run Python can run a dashboard built by this skill. The starter template loads HTML/CSS/JS from sibling files so the design is editable in a syntax-highlighted editor without touching Python.

What ships in the box

local-dashboard-builder/
├── README.md
├── LICENSE                             # MIT
├── CHANGELOG.md
├── VERSION                             # semver, single source of truth
├── install.sh / install.py             # install into an existing repo
├── .claude-plugin/plugin.json          # Claude plugin manifest
├── .claude/scripts/local-dashboard-builder-update.py  # end-user update script (prefix-named to coexist with other plugins)
├── skills/local-dashboard-builder/
│   ├── SKILL.md                        # 7-phase workflow, the contract
│   ├── templates/                      # dashboard.html / .css / .js + server.py + storage.py + favicon.svg
│   │   └── download_echarts.py         # optional ECharts vendoring (scatter / heatmap)
│   ├── references/                     # planning-workflow, design-principles, data-contract, example-collectors
│   └── scripts/
│       ├── scaffold.py                 # drop a starter dashboard into any repo
│       ├── validate.py                 # check a dashboard-manifest.md against the schema gates
│       └── indexer.py                  # JSONL -> SQLite rebuilder
└── examples/
    ├── minimal/                        # all nine panel kinds, fake data
    └── engagements/                    # realistic portfolio dashboard, SQLite event log, URL filters

Contributing

Issues and PRs welcome at https://github.com/walm00/local-dashboard-builder. The plugin follows the 7-phase workflow itself — changes to templates or the skill should update CHANGELOG.md and, where relevant, the reference docs.

License

MIT — see LICENSE.

About

A Claude plugin that turns any repo into a zero-dependency localhost HTML dashboard via a manifest-tracked 7-phase workflow.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors