Developer Guide
You've cloned the repo and want to understand or extend chartjs2img. This page points you to the right spot for each kind of change.
What this project is
A thin service around Chart.js rendered inside headless Chromium:
Everything on the Node side is written so it can run unchanged under bun --compile — there's no build step required for development.
Repo layout
chartjs2img/
├── src/
│ ├── index.ts # CLI entry point: argv parser, subcommand dispatch
│ ├── cli.ts # `render` + `examples` CLI implementations
│ ├── server.ts # `serve` HTTP server (Bun.serve)
│ ├── renderer.ts # Puppeteer + Chromium lifecycle, screenshot pipeline
│ ├── template.ts # Static HTML template loaded in the browser
│ ├── cache.ts # In-memory LRU + TTL cache
│ ├── semaphore.ts # Tiny async semaphore for concurrency control
│ ├── examples.ts # Built-in chart examples (used by CLI + gallery)
│ ├── version.ts # Single source of truth for VERSION
│ └── llm-docs/ # Per-module LLM-oriented Markdown snippets
│ ├── index.ts # Aggregates + exports getLlmDocs()
│ ├── usage.ts
│ ├── chartjs-core.ts
│ ├── plugin-*.ts
│ ├── chart-*.ts
│ └── adapter-*.ts
├── examples/ # JSON inputs + PNG outputs (regenerable)
├── docs/ # VitePress bilingual documentation site
├── .github/workflows/ # CI
├── Dockerfile
├── package.json
└── README.mdThe code base is intentionally small (~2000 LOC excluding llm-docs) — all the heavy lifting happens inside Chromium. When you're reading, the interesting file is usually renderer.ts.
Common contribution flows
"I want to add another Chart.js plugin"
"I want to document a plugin for LLMs"
See Adding LLM docs.
"I want to tune concurrency / cache / browser behavior"
See Architecture for the moving parts, then check Modules for which file to edit. Most knobs are env vars — no rebuild needed.
"I hit a bug in rendering"
Check the browser console first. In renderer.ts, page.on('console', …) and window.__chartMessages capture both Chromium-side and Chart.js-side errors. They surface to the caller via X-Chart-Messages (HTTP) or stderr (CLI) — see Error handling.
Running from source
bun install
bun run dev # HTTP server on :3000
bun run cli -- help # CLI help
bun run cli -- llm # LLM reference outputbun run prepends the project's local binaries and doesn't need a compiled binary. Type check with bun run typecheck.
Running the full site locally
bun run docs:dev # VitePress dev server on :5173The docs site has no backend. It reads docs/en/** and docs/ja/**, plus the sidebar/nav defined in docs/.vitepress/config.ts.
Where to go next
- Library API (TypeScript) — import
renderChartand friends from any Bun / Node program. - Architecture — request flow from HTTP to PNG.
- Modules — one-line summary of each
src/*.tsfile. - Types & HTTP schema — every interface and every HTTP body.
- Adding a Chart.js plugin — 3-file change, <10 lines.
- Adding LLM docs — add a plugin's option table to
chartjs2img llm. - Error handling — how renderer errors / Chart.js errors / server errors differ.