{"id":51201148,"url":"https://github.com/shuakami/paperchart","last_synced_at":"2026-06-28T00:30:46.932Z","repository":{"id":353308542,"uuid":"1218930940","full_name":"shuakami/paperchart","owner":"shuakami","description":"Quiet, editorial chart PNGs for technical blog posts. 15 primitives, six themes, one CLI.","archived":false,"fork":false,"pushed_at":"2026-04-23T11:07:55.000Z","size":0,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-23T11:29:54.854Z","etag":null,"topics":["agent-skills","agentskills","anthropic-style","blog","charts","data-visualization","editorial","linear-style","minimal-design","openai-style","playwright","react","recharts","skills-sh","technical-writing","typescript","vercel-style"],"latest_commit_sha":null,"homepage":"https://shuakami.github.io/paperchart/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shuakami.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-23T11:05:43.000Z","updated_at":"2026-04-23T11:05:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/shuakami/paperchart","commit_stats":null,"previous_names":["shuakami/paperchart"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/shuakami/paperchart","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fpaperchart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fpaperchart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fpaperchart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fpaperchart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shuakami","download_url":"https://codeload.github.com/shuakami/paperchart/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuakami%2Fpaperchart/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34873663,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-skills","agentskills","anthropic-style","blog","charts","data-visualization","editorial","linear-style","minimal-design","openai-style","playwright","react","recharts","skills-sh","technical-writing","typescript","vercel-style"],"created_at":"2026-06-28T00:30:46.851Z","updated_at":"2026-06-28T00:30:46.923Z","avatar_url":"https://github.com/shuakami.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# paperchart\n\n![paperchart — clean charts for technical writing](./public/og.png)\n\nClean chart PNGs for technical blog posts. One command in, one image out.\n\n```bash\nnpx github:shuakami/paperchart latency -i data.json -o latency.png\n```\n\nOr install as an open agent skill so Claude Code, Cursor, Codex and Gemini can pick the style up automatically:\n\n```bash\nnpx skills add shuakami/paperchart\n```\n\nThirty-two chart primitives (including Mermaid-style flowchart, architecture, sequence, state, and ER diagrams), six themes, a headless-Chromium pipeline that renders every figure at 2\u0026times;-DPR. Designed to be driven by AI agents \u0026mdash; feed it a structured JSON file, get a figure you can ship.\n\n---\n\n## Gallery\n\nA quick look at every primitive. Each one is rendered live on the [landing page](https://shuakami.github.io/paperchart/) and can be re-rendered into a PNG with the CLI.\n\n### Tables and rankings\n\n| | |\n| --- | --- |\n| ![table](./docs/screenshots/table.png) | ![ranking](./docs/screenshots/ranking.png) |\n| **`table`** \u0026mdash; column-major comparison table for model / product / tier release posts. | **`ranking`** \u0026mdash; sorted leaderboard with one accented row, for eval rankings and top-N lists. |\n\n### Bars and distributions\n\n| | |\n| --- | --- |\n| ![latency](./docs/screenshots/latency.png) | ![bytes](./docs/screenshots/bytes.png) |\n| **`latency`** \u0026mdash; grouped horizontal bars, log-scaled x axis, for percentile comparisons. | **`bytes`** \u0026mdash; stacked horizontal bars with an explicit gap, for first-load vs deferred payloads. |\n| ![stacked-bar](./docs/screenshots/stacked-bar.png) | ![grouped-bar](./docs/screenshots/grouped-bar.png) |\n| **`stacked-bar`** \u0026mdash; per-row segment stack, for composition of a measure across categories. | **`grouped-bar`** \u0026mdash; side-by-side bars per group, for two to four series compared across groups. |\n| ![dumbbell](./docs/screenshots/dumbbell.png) | ![slope](./docs/screenshots/slope.png) |\n| **`dumbbell`** \u0026mdash; paired before / after endpoints per row, bi-temporal comparisons at a fixed moment. | **`slope`** \u0026mdash; two-point lines per series, simple before / after trend. |\n| ![histogram](./docs/screenshots/histogram.png) | ![box-plot](./docs/screenshots/box-plot.png) |\n| **`histogram`** \u0026mdash; frequency bins, for distribution shape. | **`box-plot`** \u0026mdash; five-number-summary rows, for distribution comparison. |\n| ![cdf](./docs/screenshots/cdf.png) | ![waterfall](./docs/screenshots/waterfall.png) |\n| **`cdf`** \u0026mdash; cumulative distribution, for tail-sensitive comparisons. | **`waterfall`** \u0026mdash; signed-delta steps, for build-ups and break-downs. |\n\n### Time, flow, and structure\n\n| | |\n| --- | --- |\n| ![line](./docs/screenshots/line.png) | ![area](./docs/screenshots/area.png) |\n| **`line`** \u0026mdash; multi-series time series, the classical line chart. | **`area`** \u0026mdash; stacked area, for composition over time. |\n| ![small-multiples](./docs/screenshots/small-multiples.png) | ![timeline](./docs/screenshots/timeline.png) |\n| **`small-multiples`** \u0026mdash; N panels sharing axes, per-segment sparkline grid. | **`timeline`** \u0026mdash; swim-lane phases on a time axis, for roadmaps and release histories. |\n| ![funnel](./docs/screenshots/funnel.png) | ![sankey](./docs/screenshots/sankey.png) |\n| **`funnel`** \u0026mdash; stage bars with drop-off annotations, for acquisition / activation funnels. | **`sankey`** \u0026mdash; two-column flow diagram, for attribution and token allocation. |\n| ![treemap](./docs/screenshots/treemap.png) | ![radar](./docs/screenshots/radar.png) |\n| **`treemap`** \u0026mdash; squarified hierarchical tiles, for bundle / budget composition. | **`radar`** \u0026mdash; multi-axis polygon, for capability profile and coverage map. |\n\n### Matrices, points, calendars\n\n| | |\n| --- | --- |\n| ![scatter](./docs/screenshots/scatter.png) | ![heatmap](./docs/screenshots/heatmap.png) |\n| **`scatter`** \u0026mdash; points + optional regression, for correlation plots. | **`heatmap`** \u0026mdash; row \u0026times; column matrix, for confusion matrices and cross-tabs. |\n| ![calendar-heatmap](./docs/screenshots/calendar-heatmap.png) | ![recall](./docs/screenshots/recall.png) |\n| **`calendar-heatmap`** \u0026mdash; 53\u0026times;7 daily grid, daily activity over a year. | **`recall`** \u0026mdash; per-row dot plot with overlapping markers, showing two engines return the same set. |\n\n### Architecture and explanation\n\n| | |\n| --- | --- |\n| ![critical-path](./docs/screenshots/critical-path.png) | ![pack-layout](./docs/screenshots/pack-layout.png) |\n| **`critical-path`** \u0026mdash; horizontal timeline with named milestones, for resource waterfalls. | **`pack-layout`** \u0026mdash; byte-level composition + bit header, for explaining a binary format. |\n| ![delivery](./docs/screenshots/delivery.png) | ![flowchart](./docs/screenshots/flowchart.png) |\n| **`delivery`** \u0026mdash; three-up panel comparison, for architecture options where one variant is emphasised. | **`flowchart`** \u0026mdash; layered DAG with decisions and stores, for request pipelines and retry logic. |\n| ![architecture](./docs/screenshots/architecture.png) | ![sequence](./docs/screenshots/sequence.png) |\n| **`architecture`** \u0026mdash; grouped services with labelled connections, for system architecture diagrams. | **`sequence`** \u0026mdash; lifelines with directed messages and notes, for API request flows. |\n| ![state-diagram](./docs/screenshots/state-diagram.png) | ![er-diagram](./docs/screenshots/er-diagram.png) |\n| **`state-diagram`** \u0026mdash; states with labelled transitions and pseudostates, for UI state machines. | **`er-diagram`** \u0026mdash; entity boxes with crow's-foot cardinality, for database schema walkthroughs. |\n\nAll thirty-two are also live at [shuakami.github.io/paperchart](https://shuakami.github.io/paperchart/). Pass `?theme=ink` (or `slate` / `forest` / `mono` / `dusk`) to see any of them in another palette.\n\n---\n\n## Quick start\n\n```bash\n# pick any chart type, point it at JSON, name the output:\nnpx github:shuakami/paperchart latency -i data.json -o out/latency.png\nnpx github:shuakami/paperchart bytes   -i data.json -o out/bytes.png\nnpx github:shuakami/paperchart recall  -i data.json -o out/recall.png\n\n# render a sample without writing any JSON first:\nnpx github:shuakami/paperchart latency --defaults -o sample.png\n```\n\nThe CLI starts a tiny local HTTP server, renders the React view inside headless Chromium, screenshots it, and exits. No dev server to run, no `npm install` inside your project, no React editing.\n\n**First run** downloads the Chromium binary (~200\u0026nbsp;MB). Re-runs are fast.\n\n## The chart primitives\n\n| slug | what it is | good for |\n| --- | --- | --- |\n| `table` | column-major comparison table | model / product / tier release posts |\n| `latency` | grouped horizontal bars, log-scaled x axis | before / after distributions, percentile comparisons |\n| `bytes` | stacked horizontal bars with an explicit gap | splitting a payload into a first-load block and a deferred block |\n| `stacked-bar` | per-row segment stack | composition of a measure across categories |\n| `grouped-bar` | side-by-side bars per group | two to four series compared across groups |\n| `ranking` | sorted leaderboard with one accented row | eval rankings, top-N lists |\n| `dumbbell` | paired before / after endpoints per row | bi-temporal comparison at a fixed moment |\n| `slope` | two-point lines per series | simple before / after trend |\n| `line` | multi-series time series | classical line chart |\n| `area` | stacked area | composition over time |\n| `small-multiples` | N panels sharing axes | per-segment sparkline grid |\n| `timeline` | swim-lane phases on a time axis | roadmaps, release histories |\n| `funnel` | stage bars with drop-off annotations | acquisition / activation funnels |\n| `sankey` | two-column flow diagram | attribution, token allocation |\n| `treemap` | squarified hierarchical tiles | bundle / budget composition |\n| `radar` | multi-axis polygon | capability profile, coverage map |\n| `scatter` | points + optional regression | correlation plots |\n| `heatmap` | row \u0026times; column matrix | confusion matrices, cross-tabs |\n| `calendar-heatmap` | 53\u0026times;7 daily grid | daily activity over a year |\n| `histogram` | frequency bins | distribution shape |\n| `box-plot` | five-number-summary rows | distribution comparison |\n| `cdf` | cumulative distribution | tail-sensitive comparisons |\n| `waterfall` | signed-delta steps | build-ups and break-downs |\n| `critical-path` | horizontal timeline with named milestones | network waterfalls, deferred vs blocking resources |\n| `pack-layout` | byte-level composition + bit header | explaining a binary format on a single page |\n| `recall` | per-row dot plot with overlapping markers | showing that two or more engines return the same result set |\n| `delivery` | three-up panel comparison | architecture options where only one variant is emphasised |\n| `flowchart` | layered DAG with decisions and stores | request pipelines, retrieval flows, retry logic |\n| `architecture` | grouped services with labelled connections | system architecture diagrams |\n| `sequence` | lifelines with directed messages and notes | API request flows, RPC traces |\n| `state-diagram` | states with labelled transitions and pseudostates | UI and protocol state machines |\n| `er-diagram` | entity boxes with crow's-foot cardinality | database schema walkthroughs |\n\nHit each live at [shuakami.github.io/paperchart](https://shuakami.github.io/paperchart/) \u0026mdash; or scroll up to the gallery above for a pre-rendered preview of every primitive.\n\n## JSON schemas\n\nEvery type takes a single JSON document. Numbers stay raw; the renderer handles units, alignment, colour.\n\n### `latency` \u0026mdash; `Row[]`\n\n```jsonc\n[\n  {\n    \"group\": \"baseline\",\n    \"caption\": \"fuzzy scoring over the JSON index shipped inside the chunk\",\n    \"color\": \"neutral\",            // \"neutral\" | \"accent\"\n    \"bars\": [\n      { \"level\": \"p50\", \"ms\": 13.32 },\n      { \"level\": \"p95\", \"ms\": 23.94 },\n      { \"level\": \"p99\", \"ms\": 25.41 }\n    ]\n  },\n  { \"group\": \"inverted index\",   \"caption\": \"...\", \"color\": \"neutral\", \"bars\": [ /* ... */ ] },\n  { \"group\": \"externalized pack\", \"caption\": \"...\", \"color\": \"accent\",  \"bars\": [ /* ... */ ] }\n]\n```\n\nRow count is fixed at 3 in v0.1.\n\n### `bytes` \u0026mdash; `Row[]`\n\n```jsonc\n[\n  {\n    \"group\": \"baseline\",\n    \"caption\": \"index + pages JSON inlined as a string literal inside the JS chunk\",\n    \"accent\": false,\n    \"segments\": [\n      { \"kb\": 87, \"fill\": \"neutral\", \"tag\": \"JSON index + pages\" },\n      { \"kb\": 20, \"fill\": \"neutral\", \"tag\": \"runtime + UI glue\" }\n    ],\n    \"firstLoadKB\": 107,\n    \"deferredKB\": 0\n  }\n  // up to 3 rows\n]\n```\n\n`fill` accepts `\"neutral\"` or `\"accent\"` (or a hex string, for escape hatches).\n\n### `recall` \u0026mdash; `Query[]`\n\n```jsonc\n[\n  { \"query\": \"weather\", \"hits\": 5, \"sets\": \"equal\" },\n  { \"query\": \"bilibili\", \"hits\": 7, \"sets\": \"equal\" },\n  { \"query\": \"图片\",     \"hits\": 12, \"sets\": \"equal\" }\n  // 20 queries in the default layout\n]\n```\n\n### `critical-path` \u0026mdash; `Row[]`\n\n```jsonc\n[\n  { \"label\": \"index.html\",       \"detail\": \"server-rendered document shell\", \"startMs\": 0,   \"endMs\": 40,  \"kb\": 4,  \"critical\": true },\n  { \"label\": \"framework runtime\",\"detail\": \"React runtime chunk\",            \"startMs\": 30,  \"endMs\": 140, \"kb\": 48, \"critical\": true },\n  { \"label\": \"/search-pack.bin\", \"detail\": \"fetched only when user searches\",\"startMs\": 620, \"endMs\": 760, \"kb\": 78, \"critical\": false }\n]\n```\n\n6 rows in the default layout.\n\n### `pack-layout` \u0026mdash; `Segment[]`\n\n```jsonc\n[\n  { \"label\": \"Docs\",        \"detail\": \"id, title, url, summary\",                  \"bytes\": 51842,  \"accent\": false },\n  { \"label\": \"Tokens\",      \"detail\": \"type flag + bytes + posting deltas\",       \"bytes\": 212908, \"accent\": true  },\n  { \"label\": \"Corrections\", \"detail\": \"spell-correction candidates\",              \"bytes\": 37270,  \"accent\": false }\n]\n```\n\n### `delivery` \u0026mdash; panel spec\n\n```jsonc\n{\n  \"header\": \"how search reaches the browser\",\n  \"subheader\": \"same corpus, three delivery shapes\",\n  \"panels\": [\n    {\n      \"title\": \"baseline\",\n      \"subtitle\": \"JSON index + pages inlined inside the JS chunk\",\n      \"accent\": false,\n      \"assets\": [\n        { \"label\": \"docs JS chunk\", \"detail\": \"pages JSON + index + UI\", \"kb\": 87, \"kind\": \"main\" },\n        { \"label\": \"runtime\",       \"detail\": \"shipped in the same chunk\", \"kb\": 20, \"kind\": \"main\" }\n      ],\n      \"note\": \"Index, scorer and UI all travel together in the first-paint payload.\"\n    }\n    // up to 3 panels\n  ]\n}\n```\n\n## CLI flags\n\n```\npaperchart \u003ctype\u003e -i data.json -o out.png [options]\n\n  -i, --input \u003cpath\u003e    Path to JSON input.\n  -o, --output \u003cpath\u003e   Path to PNG output.\n      --defaults        Render the built-in sample (skip -i).\n  -w, --width \u003cpx\u003e      Viewport width in CSS pixels. Default 1600.\n      --dpr \u003cfactor\u003e    Device pixel ratio. Default 2.\n      --help            Print usage.\n```\n\n## Themes\n\nEvery chart reads a five-token theme \u0026mdash; `bg`, `ink`, `muted`, `accent`, `secondary`, `rule`. No hex is hard-coded inside chart code; the same JSON renders into any theme by passing `--theme \u003cname\u003e`.\n\n| name | feel | accent |\n| --- | --- | --- |\n| `paper` | warm off-white, the default | rust `#C75F3C` |\n| `ink` | near-white, OpenAI research | graphite `#111111` |\n| `slate` | cool neutral, Stripe Press | deep blue `#3B5BDB` |\n| `forest` | warm off-white, foliage accent | green `#2F6B48` |\n| `mono` | pure monochrome | black `#000000` |\n| `dusk` | charcoal background, warm orange | amber `#E58A4A` |\n\nNo gradients, no shadows, no decorative rounded corners. Inline labels beat titles.\n\n## Deeper customisation\n\nIf you need something the CLI does not cover \u0026mdash; different sizes, an extra annotation layer, a different colour \u0026mdash; clone the repo and edit the TSX directly:\n\n```bash\ngit clone https://github.com/shuakami/paperchart.git\ncd paperchart\nnpm install\nnpm run dev          # live preview at http://127.0.0.1:5173/\nnpm run snap         # render every chart to ./out/*.png\n```\n\nEach chart lives in its own file under [`src/charts/`](./src/charts); the default data array is at the top. Edit the numbers, save, open the URL \u0026mdash; everything re-renders.\n\n## Installing as an agent skill\n\nThis repo follows the [agentskills.io specification](https://agentskills.io/specification): a root [`SKILL.md`](./SKILL.md) teaches agents the overall style and how to call the CLI; focused per-chart skills live under [`skills/`](./skills).\n\n```bash\nnpx skills add shuakami/paperchart\n```\n\nAfter install, the skill is visible to Claude Code, Cursor, Codex, Gemini CLI and anything else that loads SKILL.md files from `.agents/skills/` or `.claude/skills/`. Agents will know the palette, the typography rules, the six chart shapes, and how to call `paperchart` from the shell.\n\n## License\n\nMIT \u0026copy; [shuakami](https://github.com/shuakami)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshuakami%2Fpaperchart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshuakami%2Fpaperchart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshuakami%2Fpaperchart/lists"}