GitHub Stats Dashboard: Real Data, Real Time
GitHub Stats Dashboard: Real Data, Real Time
When building a portfolio, showing what you do is one thing. Showing how active you are is another level entirely.
I wanted my About page to have more than just a static list of skills. I wanted it to breathe with real data from GitHub — contributions, stars, and a beautiful contribution heatmap.
The Challenge
GitHub's public API is powerful, but it has quirks:
- The Events API often returns
PushEvententries without commit data (commits: 0) - Rate limits are strict: 60 requests/hour without auth, 5,000 with a token
- The Contributions API isn't official — I had to use
github-contributions-api.jogruber.de
The Solution
1. Fetching the Data
I created a GithubStats.tsx component that fetches from three sources:
// GitHub user profile (for public repos count)
const profileRes = await fetch("https://api.github.com/users/rafaelsanoli");
// All repos (to calculate total stars)
const reposRes = await fetch("https://api.github.com/users/rafaelsanoli/repos?per_page=100");
const totalStars = reposData.reduce((acc, repo) => acc + repo.stargazers_count, 0);
// Contributions heatmap data
const contribRes = await fetch("https://github-contributions-api.jogruber.de/v4/rafaelsanoli?y=last");
2. The Contribution Graph
The most visually striking part is the contribution heatmap. I built a separate ContributionGraph.tsx component that:
- Breaks down 365 days into weeks (7-day chunks)
- Maps contribution levels (0-4) to neon cyan opacity and glow shadows
- Uses Tailwind's
box-shadowfor that cyberpunk aesthetic
const getLevelColor = (level: number) => {
switch (level) {
case 0: return "bg-white/5";
case 1: return "bg-[#00f3ff]/20 shadow-[0_0_5px_rgba(0,243,255,0.2)]";
case 2: return "bg-[#00f3ff]/40 shadow-[0_0_8px_rgba(0,243,255,0.4)]";
case 3: return "bg-[#00f3ff]/60 shadow-[0_0_12px_rgba(0,243,255,0.6)]";
case 4: return "bg-[#00f3ff] shadow-[0_0_15px_rgba(0,243,255,0.8)]";
default: return "bg-white/5";
}
};
3. The Bug That Broke Everything
Initially, I tried to display Latest Activity by fetching commit messages from the Events API. But I hit a wall:
{
"type": "PushEvent",
"repo": "rafaelsanoli/modula",
"commits": 0, // ❌ Empty!
"first_commit": null
}
GitHub's API sometimes returns PushEvents without commit details. The fix? I tried fetching commits directly from the most recently updated repos, but ultimately decided to remove the feature because:
- It wasn't reliable
- Real-time commit tracking requires webhooks (impossible on a static site)
- The heatmap already shows activity trends
What I Learned
- Error Handling is King: Always add
?.optional chaining when dealing with APIs - Defensive Programming: Filter out bad data before mapping:
eventsData.filter(event => event.type === "PushEvent" && event.payload?.commits?.length > 0) - Know When to Quit: Sometimes removing a feature is better than shipping a broken one
The Result
Now my About page displays:
- 15 Public Repos
- 3 Total Stars (and counting!)
- 222 Contributions in the last year
- A glowing, interactive Contribution Heatmap
All fetched in real-time, every time someone visits the page.
Try It Yourself
Check out the live dashboard on my About page, or explore the code on GitHub.
Tech Stack: Next.js, TypeScript, Tailwind CSS, GitHub API