A Spotify-Wrapped-style year in review for any GitHub profile — paste a profile link, and it unwraps that developer's year as a full-screen, animated story. All data is pulled live from public APIs at runtime. No backend, no database, nothing hardcoded.
Recreated as a production React app from a Claude Design handoff bundle, then rewired to derive everything from a real GitHub profile.
- Home screen — drop a GitHub profile (
github.com/torvalds,@torvalds, or justtorvalds) and pick a year. - The app fetches and derives the whole story client-side, then plays it back as 11 story slides.
Three public, CORS-open sources — called straight from the browser:
| Source | Powers |
|---|---|
api.github.com/users/{u} |
name, avatar, public repos, followers |
api.github.com/users/{u}/repos |
stars, top repos, language mix |
github-contributions-api.jogruber.de |
the contribution calendar → heatmap, streak, active days, busiest day, busiest month |
api.github.com/search/issues (best-effort) |
PRs merged / opened, issues opened |
Your developer archetype is derived from those real metrics (streak length, weekend ratio, top language, stars) — not picked from a hardcoded list.
Honest by design: stats GitHub doesn't expose publicly (hour-of-day activity, lines added/removed) are simply not shown rather than faked. When the search API is rate-limited, those slides say so instead of inventing numbers.
Intro · Total contributions · Streak + contribution grid · Stars & repos · Top repository (+ leaderboard) · Languages · Most active month · Busiest weekday · Pull requests & issues · Developer archetype · Shareable poster.
- Click the right two-thirds to advance, the left third to go back
→/Spacenext ·←previous ·Ppause/play- Auto-play advances on a per-slide timer (pauses when the tab is hidden)
- The progress bars up top are clickable — jump to any slide
- The GH mark (top-left) returns home to unwrap another profile
- The ⚙ gear (bottom-right) opens Tweaks: palette (Green / Synth / Sunset), display font, auto-play, and seconds-per-slide
- Vite + React 18 + TypeScript (strict)
- Zero runtime UI dependencies — pure CSS for layout, animation, and theming
- Fonts via Google Fonts (Bricolage Grotesque, Space Grotesk, Archivo, Syne, JetBrains Mono)
- Animation end-states are visible by default, so a stalled animation clock (inactive tab, print, PDF export) never leaves a blank slide.
- Count-ups have a timer safety net so the final number always lands.
- Only the active slide is mounted (keyed remount), re-triggering entrances and count-ups cleanly.
Unauthenticated GitHub REST is 60 requests/hour per IP and search is ~10/minute, so a burst of lookups can hit a limit — the app surfaces a clear message and a retry. No token is required (or stored) for normal use.
npm install
npm run dev # http://localhost:5173
npm run build # type-check + production build → dist/
npm run preview # serve the production build locallyA static SPA — deploys to Vercel with zero config (Vite preset:
npm run build → dist/). vercel.json adds the SPA rewrite.
vercel --prodsrc/
main.tsx # entry point
App.tsx # home (profile input) → fetch → Story engine
github.ts # live data layer: parse link, fetch, derive WrappedData
slides.tsx # the eleven slide components
data.ts # theme palettes + Linguist language colors (reference only)
hooks.ts # useCountUp + formatters
types.ts # shared types
styles.css # the full design system
TweaksPanel.tsx # floating settings panel + form controls
components/
atoms.tsx # Eyebrow, MiniStat, ContribGrid
Designed in Claude Design and implemented with Claude Code. Profile data belongs to its respective GitHub users and is fetched live; nothing is stored.