Chart any public GitHub user's monthly contributions since 2021, overlaid with the launch dates of major AI coding models (ChatGPT, GPT-4, Claude, etc.).
Live at: https://github-contributions.com
Made by @joshferge.
A single Cloudflare Worker serves:
/— a staticindex.html(frompublic/) rendered by Chart.js with a dashed-rule annotation for each AI model launch. Title, subtitle, and total are drawn on the canvas itself so shared/exported PNGs are self-contained./api/chart?username=<handle>&from=<year>— fetches the GitHub GraphQLcontributionsCollectionyear-by-year, aggregates into monthly buckets, and returns JSON. Smoothing (3-month moving average) is computed client-side so the toggle doesn't require a refetch.
Marker dates are a static list hardcoded on the frontend in
public/index.html (the MARKERS array). No API call is needed for them.
/api/chart responses are cached at the Cloudflare edge for 1 hour per
(username, from-year) so a burst of traffic doesn't eat through the
GitHub GraphQL rate limit.
- Cloudflare Workers + static assets (via
wrangler.jsonc) - TypeScript (worker) — no build step; Wrangler handles bundling
- Vanilla HTML/CSS/JS (frontend) with Chart.js 4.x +
chartjs-plugin-annotationloaded from a CDN - Geist + JetBrains Mono (Google Fonts)
No framework, no database, no bundler config beyond Wrangler.
src/index.ts Worker: routes, GitHub GraphQL fetch, aggregation, cache
public/index.html Frontend: hero, search, controls, chart, share buttons
wrangler.jsonc Worker config (name, main, assets dir, compat date)
package.json Dev deps only (wrangler, workers-types, typescript)
tsconfig.json TS config for editor type-checking
npm install
npx wrangler login # once, OAuth to Cloudflare
gh auth token | npx wrangler secret put GITHUB_TOKEN
npm run dev # starts wrangler devThe GITHUB_TOKEN secret is required for any GitHub GraphQL call. The gh
CLI token works fine (needs no specific scopes for public contribution data).
A fine-grained PAT with zero scopes is the safer long-term option.
npm run deployDeploys to the account you logged into with wrangler login. First deploy
creates the Worker; subsequent deploys update it.
gh auth token | npx wrangler secret put GITHUB_TOKENMarkers live in one place: the MARKERS array in public/index.html. Each
entry is { date: "YYYY-MM-DD", label: "..." }. Add, remove, or reword
entries and npm run deploy.
The OG image served at /og.png is rasterized from scripts/og.svg. To
regenerate after editing the SVG:
brew install librsvg # once
rsvg-convert -w 1200 -h 630 scripts/og.svg -o public/og.pngThe favicon (public/favicon.svg) is a plain SVG and needs no build step.
Buttons appear once a chart renders:
- Share on X — opens
twitter.com/intent/tweetwith prefilled text + the permalink. The permalink includes?u=<handle>, so clicking the shared link lands directly on the recipient's chart. - Copy link — just the permalink.
- Copy image — writes a PNG of the chart canvas to the clipboard via the
async Clipboard API (Safari-compatible: Promise is passed directly to
ClipboardItem). Falls back to a file download if the clipboard is unavailable. - Download PNG — direct download.
MIT.