A modular, registry-driven chart generator for AI agents. Produces self-contained HTML pages with styled charts and tables — no backend required.
Design philosophy: Only load the CSS/JS/docs for chart types actually used, minimizing token waste. All information is statically readable with no hover dependency.
typeNameDescriptionheatmapMatrix Heatmap TableMulti-row x multi-column numeric matrix with color-coded cells, change arrows, and trend badgeslayeredTiered Category CardsThree-tier color-coded cards (green/blue/red) for categorizing items by performance leveldirectionRecommendation CardsDual-column cards with auto-matched icons and color themeslineMulti-series Line ChartChart.js multi-line chart with optional data labelsdualAxisDual-axis Line ChartChart.js dual Y-axis: primary series (area fill) + secondary series (dashed line)tableStyled TableClean white-background table with auto-coloring for ↑/↓ prefixed cellstextText BlockColored callout blocks: success (green) / warning (yellow) / danger (red)
Full data format specs are in templates/types/{type}.md — read on demand.
Based on the user's request, select the needed chart types from the table above.
Read skills/chart-renderer-open/templates/registry.json for file mappings
Read skills/chart-renderer-open/templates/chart_page.html for the page skeleton
Read skills/chart-renderer-open/templates/types/core.css for shared styles
For each needed type, read its .md file for data format, its .css and .js for rendering code
line and dualAxis share chart.css/ chart.js), do not re-readBuild the CFG and SECTIONS data structures per the .md format specs.
Data injection uses JSON. The skeleton template loads data via <script type="application/json"> + JSON.parse. Both data placeholders must contain valid JSON strings (output of JSON.stringify()). This means:
" in string values must be escaped as \"\nJSON.stringify() to outputPlaceholderFill with{{PAGE_TITLE}}Page title<!--__CDN_LIBS__*/CDN scripts (include Chart.js + datalabels when line/dualAxis used; always include html2canvas)/*__CORE_CSS__*/core.css content/*__TYPE_CSS__*/Concatenated CSS for needed types/*__TYPE_JS__*/Concatenated JS for needed types/*__CFG__*/{}/*__END__*/JSON string of CFG object/*__SECTIONS__*/[]/*__END__*/JSON string of SECTIONS array
docs/{chart_types}_report_{year}_{month}_{day}_{hour}_{minute}_{second}.html (no zero-padding)/home/admin/.openclaw/canvas/documents/report_{id}/index.html[embed ref="report_{id}" title="Report Preview" height="600" /] in reply for inline preview{typeName}.css, {typeName}.js, {typeName}.md under types/registerRenderer('typeName', renderFn) or registerRenderer('typeName', renderFn, afterRenderFn)registry.json