Skip to content

Cluka-399/chart-image

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“Š chart-image

Publication-quality chart images from data. No browser, no Puppeteer, no native compilation.

Generate beautiful PNG charts directly from JSON data β€” perfect for bots, dashboards, alerts, and automated reports. Runs anywhere Node.js runs.

Line chart example

Why chart-image?

Most chart libraries need a browser (Puppeteer, Playwright) or native dependencies (canvas, cairo). That means 400MB+ installs, painful Docker builds, and slow cold starts.

chart-image uses Vega-Lite + Sharp with prebuilt binaries:

chart-image Puppeteer + Chart.js QuickChart.io
Install size ~15MB ~400MB+ 0 (API)
Native deps None Chromium N/A
Cold start <500ms 2-5s Network latency
Offline βœ… βœ… ❌
Fly.io/Docker Just works Pain Depends on uptime

Install

Via ClawHub (recommended)

clawhub install chart-image

Manual

git clone https://github.com/Cluka-399/chart-image.git skills/chart-image
cd skills/chart-image/scripts && npm install

Quick Start

node scripts/chart.mjs \
  --type line \
  --data '[{"x":"Mon","y":10},{"x":"Tue","y":25},{"x":"Wed","y":18}]' \
  --title "Weekly Trend" \
  --dark \
  --output chart.png

That's it. One command, one PNG.


Chart Types

πŸ“ˆ Line Chart

Track trends over time. The default chart type.

node scripts/chart.mjs --type line \
  --data '[{"x":"Mon","y":142},{"x":"Tue","y":148},{"x":"Wed","y":145},{"x":"Thu","y":155},{"x":"Fri","y":162}]' \
  --title "AAPL Weekly Price" --y-title "Price (USD)" \
  --dark --show-values --output chart.png

Line chart

πŸ“Š Bar Chart

Compare categories side by side.

node scripts/chart.mjs --type bar \
  --data '[{"x":"React","y":45},{"x":"Vue","y":28},{"x":"Svelte","y":15},{"x":"Angular","y":12}]' \
  --title "Framework Usage %" --output chart.png

Bar chart

🌊 Area Chart

Like line charts, but with filled regions to emphasize volume.

node scripts/chart.mjs --type area \
  --data '[{"x":"Jan","y":100},{"x":"Feb","y":250},{"x":"Mar","y":180},{"x":"Apr","y":420},{"x":"May","y":380},{"x":"Jun","y":520}]' \
  --title "Monthly Signups" --dark --output chart.png

Area chart

🍩 Donut / Pie Chart

Show proportions at a glance. Use --type pie for a solid circle or --type donut for the ring style.

node scripts/chart.mjs --type donut \
  --data '[{"x":"Desktop","y":58},{"x":"Mobile","y":35},{"x":"Tablet","y":7}]' \
  --title "Traffic by Device" --dark --output chart.png

Donut chart

πŸ“‰ Multi-Series Line

Compare multiple trends on one chart using --series-field.

node scripts/chart.mjs --type line \
  --data '[{"x":"Q1","y":30,"series":"2024"},{"x":"Q2","y":45,"series":"2024"},{"x":"Q3","y":52,"series":"2024"},{"x":"Q4","y":61,"series":"2024"},{"x":"Q1","y":40,"series":"2025"},{"x":"Q2","y":58,"series":"2025"},{"x":"Q3","y":72,"series":"2025"}]' \
  --title "Revenue Growth" --y-title "Revenue ($M)" \
  --series-field series --dark --legend top --output chart.png

Multi-series chart

πŸ“ Horizontal Reference Lines

Add thresholds, targets, or buy prices with --hline.

node scripts/chart.mjs --type line \
  --data '[{"x":"Jan 1","y":0.00072},{"x":"Jan 5","y":0.00085},{"x":"Jan 10","y":0.00091},{"x":"Jan 15","y":0.00078},{"x":"Jan 20","y":0.00062},{"x":"Jan 25","y":0.00071}]' \
  --title "Token Price" --y-title "Price (USD)" \
  --dark --show-values --hline "0.0008,#e63946,Buy Price" --output chart.png

Reference line chart

🎨 Conditional Colors

Color bars/points based on a threshold β€” great for KPI dashboards.

node scripts/chart.mjs --type bar \
  --data '[{"month":"Jan","score":72},{"month":"Feb","score":45},{"month":"Mar","score":38},{"month":"Apr","score":61},{"month":"May","score":29},{"month":"Jun","score":55},{"month":"Jul","score":82},{"month":"Aug","score":47},{"month":"Sep","score":68},{"month":"Oct","score":34},{"month":"Nov","score":76},{"month":"Dec","score":91}]' \
  --x-field month --y-field score --x-sort none \
  --conditional-color "50,#e63946,#2a9d8f" --hline "50,#888,Target" \
  --title "Monthly Performance Score" --subtitle "Target: 50" --dark

Conditional color chart

↔️ Horizontal Bar Charts

Flip axes for leaderboards, rankings, or long category names.

node scripts/chart.mjs --type bar \
  --data '[{"lang":"Python","stars":95},{"lang":"JavaScript","stars":82},{"lang":"TypeScript","stars":78},{"lang":"Rust","stars":71},{"lang":"Go","stars":63},{"lang":"Java","stars":58},{"lang":"C++","stars":45},{"lang":"Swift","stars":38}]' \
  --x-field lang --y-field stars --horizontal --sort desc \
  --conditional-color "60,#e63946,#2a9d8f" --bar-labels \
  --title "GitHub Stars by Language" --dark

Horizontal bar chart

More Chart Types

  • point β€” Scatter plot
  • histogram β€” Binned quantitative distribution chart
  • candlestick β€” OHLC financial charts (--open-field, --high-field, --low-field, --close-field)
  • heatmap β€” Grid visualization (--color-value-field, --color-scheme viridis)
  • Stacked bars β€” --type bar --stacked --color-field category
  • Volume overlay β€” Dual Y-axis with --volume-field
  • Sparkline β€” Tiny inline charts with --sparkline (80Γ—20, no axes)

Shorthand Syntax

Don't want to write JSON? Use the shorthand format:

node scripts/chart.mjs --type bar \
  --data "Mon:10,Tue:25,Wed:18,Thu:30,Fri:22,Sat:35,Sun:28" \
  --title "Weekly Activity" --dark --output chart.png

Shorthand example

Format: label:value,label:value,...


Dark Mode & Light Mode

Use --dark for dark backgrounds (great for Discord, Slack, dark dashboards):

Dark mode

Omit --dark for light mode (reports, emails, light UIs):

Light mode

Tip for bots: Auto-switch based on time of day β€” --dark between 20:00–07:00.


Font Families

Use --font-family with any CSS font-family stack Vega can resolve.

Need more control over headings? --title-size, --subtitle-size, --title-color, and --subtitle-color let you tune chart title typography without editing the Vega spec. Need softer dashboard gridlines? --grid-dash 4,2 adds custom dashed grid patterns without touching the Vega spec either.

Safest generic families:

  • sans-serif
  • serif
  • monospace
  • system-ui

Recommended stacks:

# Brand / product sans
--font-family "Inter, Helvetica, Arial, sans-serif"

# Editorial / report serif
--font-family "Georgia, Times New Roman, serif"

# Terminal / dashboard monospace
--font-family "JetBrains Mono, SFMono-Regular, Consolas, monospace"

Example:

node scripts/chart.mjs --type bar \
  --data '[{"month":"Jan","value":12},{"month":"Feb","value":18},{"month":"Mar","value":15},{"month":"Apr","value":22}]' \
  --x-field month --y-field value --x-sort none \
  --title "Georgia / serif example" \
  --subtitle "--font-family \"Georgia, serif\"" \
  --font-family "Georgia, serif" --dark --show-values

Font family example

Note: specific fonts like Inter, Arial, Georgia, or JetBrains Mono only work if they exist on the host. If not, Vega falls back to the next font in the stack.


Alert-Style Charts

Built-in options for monitoring and alerting use cases:

node scripts/chart.mjs --type line --data '[...]' \
  --title "Iran Strike Odds (48h)" \
  --show-change --focus-change --show-values --dark \
  --output alert.png
Flag Effect
--show-change Annotates % change from first to last value
--focus-change Zooms Y-axis to 2Γ— data range for drama
--focus-recent N Shows only the last N data points
--show-values Labels min/max peaks on the chart

Piping Data

Read from stdin:

curl -s api.example.com/metrics | node scripts/chart.mjs --type line --dark --output metrics.png
echo '[{"x":"A","y":1},{"x":"B","y":2}]' | node scripts/chart.mjs --output out.png

Options Reference

Core

Option Description Default
--type line, bar, area, point, histogram, pie, donut, candlestick, heatmap line
--data JSON array or shorthand key:val,... stdin
--output Output file path chart.png
--title Chart title β€”
--subtitle Subtitle below title β€”
--title-align Title alignment: start, middle, end start
--width Width in px 600
--height Height in px 300
--output-size Platform preset: twitter, discord, slack, linkedin, bluesky, youtube, instagram, portrait, story, thumbnail, wide, square β€”
--dark Dark theme false
--svg Output SVG instead of PNG false

Axes

Option Description Default
--x-field X axis field name x
--y-field Y axis field name y
--x-title / --y-title Axis labels field name
--x-type ordinal, temporal, quantitative ordinal
--y-domain Y range as "min,max" auto
--y-format percent, dollar, compact, decimal4, integer, scientific auto

Styling

Option Description Default
--color Primary color #e63946
--color-scheme Vega scheme (e.g. viridis, category10) β€”
--no-grid Remove gridlines false
--legend top, bottom, left, right, none β€”
--hline Reference line: "value,color,label" (repeatable) β€”

Multi-Series

Option Description
--series-field Field to split into multiple lines
--stacked Stack bars/areas
--color-field Field for color encoding
--series-order CSV Explicit series/category order for multi-series legends and stacked-bar legend/stack order

Annotations

Option Description
--show-change Show % change annotation
--focus-change Zoom Y to highlight change
--focus-recent N Show last N points only
--show-values Label min/max peaks
--last-value Label the final data point value
--annotations JSON array of event markers: [{"x":"14:00","label":"News"}]

Y-Axis Formatting

--y-format dollar    # β†’ $1,234.56
--y-format percent   # β†’ 45.2%
--y-format compact   # β†’ 1.2K, 3.4M
--y-format decimal4  # β†’ 0.0004
--y-format integer   # β†’ 1,234

Or pass any d3-format string: --y-format ',.3f'


Designed for Fly.io / VPS / Docker

This skill was built specifically for headless server environments where you can't (or don't want to) install a browser:

  • Fly.io β€” Works out of the box on flyctl deploy. No special Dockerfile needed.
  • Docker β€” No apt-get install for Cairo/Pango/etc. Just npm install.
  • VPS β€” Runs on any machine with Node.js 18+. No GPU, no display server.
  • CI/CD β€” Generate charts in GitHub Actions, GitLab CI, etc.

The secret: Vega-Lite renders to SVG natively, then Sharp (with prebuilt libvips binaries) converts to PNG. No browser in the loop.


License

MIT


Built by @Cluka-399 Β· Published on ClawHub Β· GitHub

About

Generate publication-quality chart images from data. Line, bar, area, point, candlestick, pie/donut, heatmap, multi-series, stacked charts. Designed for Fly.io/VPS - no Puppeteer, pure Node.js.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors