skills/household-finance-dashboard-builder/SKILL.md
Generates a single self-contained static HTML dashboard for a household finance JSON store, with embedded D3.js, inlined data, and six standard panels (net worth over time, monthly cash flow, recurring & subscriptions, goals progress, asset allocation, vigilance feed). Applies cognitive-design principles for visual hierarchy and visual-storytelling-design for narrative annotations. Use when emitting a weekly or monthly finance dashboard, or when user mentions weekly dashboard, household dashboard, finance HTML report, or static dashboard.
npx skillsauth add lyndonkl/claude household-finance-dashboard-builderInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This is the static-output cousin of the more general d3-visualization skill. It produces a single self-contained HTML file that opens in any browser without a server, with all data and chart code inlined. The dashboard is designed to be regenerated weekly from the household's JSON data store and committed to reports/dashboards/YYYY-MM-DD-weekly.html.
The skill assumes a JSON store conforming to the household-finance schema (accounts, transactions, balances, recurring, goals, investments, mortgage, alerts).
A single HTML file containing:
<style> block (no external CSS).<script id="dashboard-data" type="application/json">{...}</script>.<script> tag with integrity hash if offline-rendering is acceptable).visual-storytelling-design.File size target: < 1 MB. If the data exceeds this, downsample time-series before embedding (daily → weekly aggregation is usually enough).
The caller provides:
data_root — path to the household-finance data/ directory.output_path — where to write the HTML.generated_for — weekly or monthly (changes the time scope and headline).as_of — ISO date for the snapshot.prior_snapshot_path (optional) — a previous dashboard's data block for week-over-week deltas.The skill reads:
accounts.jsonbalances.jsontransactions.json (filtered to relevant window)recurring.jsongoals.jsoninvestments.jsonmortgage.jsonreports/alerts/reports/monthly/*.json for narrative context.Dashboard Build Progress:
- [ ] Step 1: Read data; validate completeness; compute snapshot
- [ ] Step 2: Compute the six panel datasets
- [ ] Step 3: Apply cognitive-design principles to layout choices
- [ ] Step 4: Generate narrative header via visual-storytelling-design
- [ ] Step 5: Render HTML scaffold + inline data + D3 code per panel
- [ ] Step 6: Run cognitive-fallacies-guard self-check on charts
- [ ] Step 7: Write to output_path; emit data quality footer
Compute the headline numbers:
net_worth_cents — sum of cash + invested + home equity estimate − liabilities (mortgage + other).delta_vs_prior_cents — vs. the prior snapshot if available.month_to_date_spend_cents, month_to_date_income_cents, month_to_date_savings_rate.goals_on_track, goals_behind, goals_ahead counts.alerts_open count.If any required file is missing, fall back gracefully: hide that panel and surface a data_gap line in the footer.
Compute exactly the data each panel needs (see The six panels). Keep arrays small — pre-aggregate to the resolution the chart needs.
Apply these defaults (delegate detailed reasoning to cognitive-design):
Invoke visual-storytelling-design to generate a 3–5 line narrative:
Build the HTML scaffold (see HTML scaffold). Inline:
renderPanel*() function per panel.Each render function follows the standard D3 data-join pattern from d3-visualization.
Before writing, run a cognitive-fallacies-guard pass on the rendered SVGs (or their data + axis configurations):
If the self-check finds issues, fix and re-render.
Write to output_path. Emit a footer with generation timestamp, schema version, last-drop date, and any data gaps.
Data: monthly net worth points from balances.json + investments.json + mortgage.json (current_principal as liability) + home equity estimate (home value - current_principal).
Chart: line chart with annotated key events (mortgage origination, large contributions, market dislocations). Y-axis starts at 0 (this is a net-worth scale where 0 matters); X-axis covers the full history.
Headline annotation: latest value + delta vs prior snapshot.
Data: per-month income (positive bars) and spending (negative bars) over the trailing 12 months, with a line showing the rolling 6-month savings rate.
Chart: diverging bar chart (income up, spending down) with savings-rate line overlay. Color: muted teal for income, muted coral for spending.
Drill-down (optional, hover): top 5 spending categories for the latest month.
Data: every active row from recurring.json, sorted by annualized_cost_cents descending.
Chart: horizontal bar chart of the top 15 by annualized cost. Each bar labeled with merchant + cadence + monthly equivalent.
Annotation: total annualized cost across all active recurring at the top. Highlight any with status: suspected_dormant or amount-changed events.
Data: every entry in goals.json with current_cents, target_cents, target_date.
Chart: horizontal stacked bar — completed vs. remaining — one row per goal. Annotate "On track / Behind / Ahead" per goal based on linear pacing to target date.
Headline: "X of Y goals on track."
Data: aggregated holdings by asset_class from investments.json (across taxable + 401k + HSA), plus the target allocation.
Chart: two donuts side by side (current vs target) OR a single donut with a target ring overlay. Label each slice directly with asset class + percentage.
Annotation: max drift in percentage points; flag if > 5pp.
Data: most recent 10 entries from reports/alerts/, severity-tagged.
Chart: a styled list — not a chart. Each entry: severity badge + one-line evidence + suggested action.
This panel is intentionally text-heavy. The dashboard is informational and operational; the user should be able to scan it and find things to do.
| Principle | Application in this dashboard | |---|---| | Pre-attentive attributes | Severity badges in the vigilance panel use color hue; everything else uses position | | Gestalt proximity | Each panel is bounded with whitespace, then a thin border, then a header | | Gestalt similarity | All numeric labels use the same monospaced font; all charts use the same axis style | | Reading order (F-pattern) | Net worth top-left; vigilance bottom-right (the actionable end of the read) | | Working memory | Max 6 categories per chart; rest aggregated | | Recognition over recall | Direct labeling — no legend-only charts | | Data-ink ratio | No 3D, no chartjunk, no decorative gradients | | Mental models | Cash flow chart uses the universally-recognized green-up/red-down convention |
The narrative header follows: Context → Change → Drivers → What needs attention.
Example:
Net worth $1,247,300 — up $4,200 this week. The increase came mostly from a $3,800 401k contribution and a small market gain in your taxable brokerage. Spending was steady at $7,840 month-to-date, slightly under your $8,500 target. One thing to watch: your portfolio drifted to 62.5% US equity, 7.5pp above your 55% target — a rebalance proposal is queued in this week's alerts.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Household Finance — [date]</title>
<style>
/* layout: 3x2 grid; max-width 1280px; light theme */
/* typography: Inter for text, JetBrains Mono for numbers */
/* colors: muted, accessible, single accent for "needs attention" */
</style>
</head>
<body>
<header>
<h1 class="net-worth-headline">$<!-- net worth --></h1>
<p class="net-worth-delta">[+/-]$<!-- delta --> this <!-- week|month --></p>
<p class="narrative">[generated narrative]</p>
</header>
<main class="grid">
<section id="panel-net-worth"></section>
<section id="panel-cash-flow"></section>
<section id="panel-recurring"></section>
<section id="panel-goals"></section>
<section id="panel-allocation"></section>
<section id="panel-vigilance"></section>
</main>
<footer>
<p>Generated [timestamp] from data/ as of [last-drop-date]. Schema version [X].</p>
<p>Data gaps: [if any].</p>
</footer>
<script id="dashboard-data" type="application/json">
{ /* inlined data */ }
</script>
<script src="https://cdn.jsdelivr.net/npm/d3@7" integrity="sha384-..." crossorigin></script>
<script>
/* renderPanelNetWorth(), renderPanelCashFlow(), renderPanelRecurring(),
renderPanelGoals(), renderPanelAllocation(), renderPanelVigilance() */
</script>
</body>
</html>
For full offline use, vendor D3 inline rather than via CDN. The dashboard agent decides per-environment.
****1234), never full account numbers. No SSNs, no full names where masks suffice.aria-labels; tabular data alternative for each chart accessible via a "Show data" toggle.development
--- name: zettel-note description: The note-writing discipline for this vault's evergreen knowledge graph, modeled on a Zettelkasten reading companion and governed by the vault conventions. Enforces declarative-claim titles, one claim per note (atomicity), own-words prose with no block quotes, the piped [[slug|Title]] link form, the labeled link-relationship vocabulary (Confirms/Contradicts/Extends/Context/Prerequisite/Builds-on/Applies/Example-of/Contrasts-with), 3-6 links per note, and search-
development
Plans between-round FIFA World Cup Fantasy transfers — budgets the round's free transfer(s), forces out players whose nation has been eliminated, chases fixture-swing drops, upgrades on value, and decides when a rebuild is large enough to fire the Wildcard instead of spending free transfers one at a time. Ranks candidate in/out pairs by EV gain over each player's remaining survival horizon (delta xEV weighted by progression_carry) MINUS transfer cost (a free transfer is cheap, a points hit is real, churning the squad for marginal swings is a critic flag), and tags forced/fixture/upgrade priority. Emits a `transfer-plan` signal. Use when called by wc-squad-architect (whose transfer work this skill is the engine for) and by the strategists in the populate stage when their candidate is transfer-adjacent rather than a full rebuild.
testing
Reads and updates the FIFA World Cup Fantasy tournament state machine (footballfantasy/context/tournament-state.md) — the temporal backbone tracking phase (pre-tournament → group MD1-3 → R32 → R16 → QF → SF → final), budget ($100m group / $105m knockouts), nation cap (3 group, loosening in knockouts), chips remaining, surviving nations, each owned player's elimination-risk horizon, and deadlines. Validates state on load (count/feasibility checks), applies phase transitions, and appends to the append-only state log (never silent overwrite). Use to load state at the start of a run and to commit state changes after the manager makes a move.
development
Validates and persists FIFA World Cup Fantasy signal files to signals/YYYY-MM-DD-<type>.md. Checks the required frontmatter (type, round, date, emitted_by, confidence, source_urls), range-checks declared numeric signals, confirms every factual claim carries a source URL or "manager-provided", rejects unknown signal types, and refuses to persist a signal that fails validation (logging the failure instead). Keeps the inter-agent signal layer auditable so downstream agents can trust what they read and never re-derive it. Use whenever an agent or skill writes a signal.