Shadcn-styled graphs for GitHub issues, lifetime commit history, npm downloads, and your own JSON data — rendered as portable SVGs.
Shadcn-styled line/area charts you can drop in a README, docs site, or anywhere an image works — plain SVG, no JavaScript, no iframe. Four kinds: GitHub issues over time, lifetime commit history (a homage to commit-history), npm downloads, and arbitrary JSON.
Star history charts are retired. GitHub restricted the stargazers API to repo admins and collaborators in June 2026, so timestamped star data can no longer be fetched for arbitrary repos. Existing
/chart/github/stars/...URLs now render a 100×1 transparent image so they don't break READMEs — swap them for an npm downloads or commit history chart.
Pick a chart kind, tweak the styling, and copy the URL or markdown.

/chart/github/issues/{owner}/{repo}.svg → GitHub issues over time
/chart/github/commits/{user}.svg → lifetime commit history
/chart/github/commits/{user1},{user2}.svg → compare users
/chart/npm/{package}.svg → npm weekly downloads
/chart/json.svg?values=1,2,3 → inline JSON data
/chart/json.svg?url=...&query=... → remote JSON data
Every endpoint also serves .png and .json (the raw time series).
Use it in markdown:

Or as a clickable image linking back to the package:
[](https://www.npmjs.com/package/zod)
Cumulative issues opened, sampled from the GitHub search API (pull requests excluded).
/chart/github/issues/{owner}/{repo}.svg
Issues opened over time
A whole coding career as one rising curve — every public commit since the account was born, accumulated month by month (the same data as the green contribution graph, not the noisy issues/PRs calendar). This is a loving homage to commit-history by Peet von Zweigbergk — "a star-history, but for commits".
/chart/github/commits/{user}.svg
Lifetime public commits, accumulated month by month
Pass comma-separated logins to race several trajectories on one chart.
/chart/github/commits/{user1},{user2},{user3}.svg
Comma-separated logins compare users on one chart
Add ?align=true for aligned mode — every user lines up at "month zero"
(their own account birth) regardless of when they actually joined, so you're
comparing trajectories rather than calendar dates.
Aligned mode — everyone starts at their own month zero
Weekly download buckets over the last year (configurable with ?days=).
/chart/npm/{package}.svg
/chart/npm/@scope/{package}.svg
Weekly npm downloads
Bring numbers inline with ?values= (comma-separated). Add ?dates= for a
time axis or ?labels= for category ticks — omit both and points are spaced
evenly and labelled 1, 2, 3, ….
/chart/json.svg?values=120,180,150,210,260&title=Latency&label=ms
/chart/json.svg?values=10,20,30&dates=2024-01-01,2024-02-01,2024-03-01
Inline values, evenly spaced index axis
Or pull from a remote endpoint with JSONPath,
exactly like the dynamic JSON badge. query
selects the value array; optional dateQuery selects a parallel date array.
/chart/json.svg?url=https://api.example.com/metrics.json&query=$.points[*].count&dateQuery=$.points[*].date
| Param | Values | Default | Description |
|---|---|---|---|
mode | dark, light | dark | Surface and text colors |
theme | blue, green, rose, orange, violet, purple, cyan, emerald, … | — | Accent color from the shadcn palette |
color | hex (no #) | 3b82f6 | Line + end-dot color (wins over theme) |
fill | hex (no #) | line color | Area fill color, independent of the line |
area | true, false | true | Show the gradient area fill under the line |
bg / background | transparent, hex | mode surface | Card background |
border | true, false | true | Draw the rounded card border |
font | inter, geist, geist-mono, jetbrains-mono, fira-code, roboto, space-grotesk | inter | Font-family stack (same keywords as badges) |
logo | false | shown | Show/hide the shieldcn corner watermark |
logoColor | hex (no #) | muted | Watermark color |
icon | SimpleIcons slug, ri:Name, false | auto (github/npm) | Icon left of the title |
iconColor | hex (no #) | title color | Title icon color |
yScale | linear, log | linear | Y-axis scale type |
yMin | number | 0 (auto) | Force the y-axis minimum |
yMax | number | auto | Force the y-axis maximum |
yTicks | 1–10 | 4 | Number of y-axis gridline intervals |
xTicks | 2–12 | 3 | Number of x-axis labels |
width | 200–2000 | 800 | Chart width in px |
height | 120–1200 | 400 | Chart height in px |
title | string | per kind | Override the chart title |
align | true, false | false | Commit charts: line users up at their account birth (month zero) |
days | 30–540 | 365 | npm download window |
values | comma numbers | — | Inline JSON data points |
dates | comma dates | — | Inline JSON x-axis dates |
labels | comma strings | — | Inline JSON x-axis labels |
url + query | URL + JSONPath | — | Remote JSON data source |
Note —
fontonly swaps the family stack. Charts are raw SVG (needed for the line paths), and a sandboxed<img>SVG can't load embedded fonts — so the rendered typeface depends on what's available to the viewer.
Star history charts reconstructed the curve from GitHub's stargazers endpoint
(/repos/{owner}/{repo}/stargazers with the star+json media type), which
returned a starred_at timestamp per stargazer. In June 2026 GitHub
restricted that endpoint
to repo admins and collaborators, so the data is no longer accessible for
arbitrary repos.
The data is still accessible in one place: a GitHub Actions workflow running
in the repo itself, where the automatic GITHUB_TOKEN has collaborator
access. The shieldcn starchart action fetches
the history there, renders the same chart card, and commits the SVG to your
repo.
To keep existing READMEs from breaking, /chart/github/stars/... URLs now
return a 100×1 transparent image (and .json returns 410 Gone pointing
at the action). If you'd rather stay on hosted charts, swap in an
issues, commits, or
npm downloads chart. The plain
stars count badge still works — it uses the repo
metadata endpoint, which is unaffected.
The commit curve is a homage to commit-history,
and works the same way it does. GitHub's GraphQL
user.contributionsCollection.totalCommitContributions returns the public
commit count for a window of at most a year, so a lifetime is sliced into
monthly windows — batched a year at a time into aliased queries — then the
counts are accumulated into the rising curve. Only public commits are counted.
Requests go through the donated token pool
with a 6-hour fresh window and a 30-day last-known-good fallback.
| Chart | Source | Cache |
|---|---|---|
| Issues | GitHub Search API (type:issue) | 6h fresh · 30d last-known-good |
| Commits | GitHub GraphQL API (contributionsCollection) | 6h fresh · 30d last-known-good |
| npm | npm downloads API | 1h |
| JSON | inline, or your url | 5m (remote) |
GitHub requests are distributed across the donated token pool and serve a last-known-good copy if the upstream is briefly unavailable.