Communitygithub.com

zluckyhou/chart-forge

Agent Skill: turn data into the right chart — interactive, validated colours, conclusion-style titles. One JSON spec, zero dependencies.

O que é chart-forge?

chart-forge is a Claude Code agent skill that agent Skill: turn data into the right chart — interactive, validated colours, conclusion-style titles. One JSON spec, zero dependencies.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add zluckyhou/chart-forge

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Chart Forge

One chart = one spec.jsonscripts/render.py → a self-contained interactive HTML file (zero dependencies; Google Fonts optional), plus a PNG when you need one. The engine handles drawing it correctly and making it look good. What the chart should say, and which form says it, is your job.

LayerWhoOwns
Expressionyou (the agent)read the data, write the one-sentence conclusion, pick the form, decide what to emphasise → spec.json
Aestheticsassets/chartkit.css + assets/palette.jsonvalidated colour tokens, type, card and tooltip styling
Renderingassets/chartkit.js + scripts/render.pySVG marks, interaction, table view, axis rounding, direct labels, PNG export

Workflow

1. Decide the message, then the form

Read references/choosing-a-form.md. Write the conclusion as one sentence — that sentence is the title. Then pick type by the job:

  • one number → kpi · change over time → line / area · compare categories → bar
  • ranking → bar + horizontal · part of a whole → donut (≤ 6 slices) · two measures → scatter (≤ 3 groups)
  • distribution across two dimensions → heatmap · price OHLC → candle · heterogeneous columns → table · step-by-step drop-off → funnel

If the data does not suit the form, reshape it first: fold a long tail into "Other" past 8 series, split scatter groups past 3, and put two measures of different magnitude in two charts — never a second y-axis.

2. Write the spec

Follow references/spec.md. Every type has a runnable example in assets/examples/ — copying the closest one and swapping the data is the fastest path.

Two lines of copy, never three: title is the conclusion, subtitle is the context (what is measured · period · unit · provenance). Use options.highlight when the story is about one entity, refLines for a target, annotations for the event that explains a turn, and reference: "average" on a ranking.

Chart chrome (buttons, table headers, tooltip labels) follows the language of the spec's own text: CJK anywhere → Chinese, otherwise English. Force it with "lang": "zh" | "en".

Use the user's real data as given. If you invent numbers to demonstrate something, say so in the subtitle or note — "sample data".

3. Render, then look at it

python3 scripts/render.py spec.json --validate                              # types, lengths, series count, funnel monotonicity…
python3 scripts/render.py spec.json -o out/chart.html                       # self-contained HTML
python3 scripts/render.py spec.json -o out/chart.html --png --theme light   # + PNG (needs Playwright)
python3 scripts/render.py a.json b.json -o out/report.html                  # several charts, one page
python3 scripts/render.py spec.json -o out/chart.html --no-webfont          # offline / intranet

Always look at the result (the PNG, or a screenshot of the page) and check it against the anti-pattern list in references/rules.md: is the title a conclusion, do labels collide, is the axis sensible, does the colour emphasise only what deserves it. Fix the spec and re-render — do not patch the engine to work around a bad spec.

4. Deliver

  • Web / report — hand over the HTML. It is one file; it also embeds in an iframe, or paste the <figure class="ck-card"> fragment together with the <style> and <script>.
  • Docs, chat, slides — hand over the PNG (--png, 2× resolution). Use --theme dark for dark decks.
  • Design canvas — inline assets/chartkit.css + assets/chartkit.js in the artboard and call ChartKit.render(host, spec) on mount.

What the engine already does for you

Know these so you do not rebuild them, and so you know what to reach for:

  • Line — end-of-line labels (series name + latest value, auto-separated when they collide), event annotations, peak marker, target lines, monotone smoothing that never overshoots.
  • Bar — hovering lights the whole category band and lists every series; the latest period is direct-labelled; stacks carry totals.
  • Ranking — rank numerals, a dashed average/target line through the bars, one highlighted subject with the rest greyed, hover swaps the value for share and distance from the reference.
  • Donut — legend rows carry proportional bars, the centre readout follows the hover, one click switches to bars when shares are too close to compare as arcs.
  • Scatter — hover drop-lines to both axes with value chips, automatic labels on the top points (skipped when they would overlap), median quadrants.
  • Heatmap — eight-step single-hue ramp or a diverging one for signed data, row/column marginal bars, hover cross-highlights the row and column labels.
  • Funnel — the neck between two steps is the drop-off, the step conversion is printed in it, the worst step is badged automatically.
  • Candle — OHLC with red-up/green-down (colors: "intl" flips it), a trading-app tooltip, an axis that frames the range instead of anchoring at zero.
  • Table — sticky header and first column, in-cell bars (barGroup to share one scale across columns), tags, two-level headers, click-to-sort.
  • KPI — value + signed pill (direction × whether up is good) + a fading sparkline.

Re-skinning to a brand

Edit assets/palette.json → mirror the values into :root and both dark blocks of assets/chartkit.css → run python3 scripts/validate_palette.py --from-json assets/palette.json. Ship only when light and dark both pass. The order of the categorical slots is the colourblind-safety mechanism, so re-validate after any reordering too.

Environment

  • HTML rendering: Python 3, no third-party packages.
  • PNG export: pip install playwright && playwright install chromium.
  • Fonts: Google Fonts (IBM Plex Sans + Noto Sans SC) by default; --no-webfont falls back to system fonts.

Habilidades Relacionadas