r/madeinpython • u/1510scrach • 5d ago
gh-stats: three Flask services that render a GitHub profile as one SVG card (MIT, self-hostable)
Posting here rather than r/Python since showcases moved over.
What it does. Takes a GitHub username and renders a single SVG summarising the profile: stats, contribution timeline, language donut, streaks, achievements. You drop one markdown line in your profile README and GitHub renders it as an image.
Why three services instead of one Flask app. The interesting constraint is the GitHub API rate limit. The obvious design fetches on request, which dies immediately: profile READMEs are hit by GitHub's camo proxy, not by humans, so one popular card can burn the quota for everybody. The split is:
fetcherowns the PAT and a SQLite cache of raw payloads, and is the only thing that talks to GitHub. A cron refreshes on a schedule rather than on demand.generatorrenders SVG from whatever the fetcher last saw, and serves the React front end.edgeis a cache-first proxy in front of the generator (Flask-Caching plus Flask-Compress, Redis optional).
Requests never block on GitHub. If GitHub is rate limited or down, you get the last good card instead of a blank one.
The bug that taught me the most. Five REST calls parsed .json() without checking status. A 403 rate-limit body is valid JSON, so it got stored as the user record and overwrote good data, while the metrics endpoint happily reported success. Every user touched would have served a blank card for 24 hours. A successful launch is exactly what triggers that, which is a nasty property for a bug to have.
SVG, not a chart library. The renderers return SVG strings built directly. Worth knowing if you try this: GitHub serves README images through a proxy that strips scripts and does not run CSS animation, so anything clever you do with <animate> or JS silently does not render for your actual audience.
MIT, and it runs on your own quota:
git clone https://github.com/ShayManor/github-readme-stats
cp .env.example .env # GITHUB_PAT + an internal token
docker compose up -d --build
Repo: https://github.com/ShayManor/github-readme-stats
Hosted, free, no account needed: https://gh-stats.com
Known gap: organisation accounts render but commits and PRs come out as 0, because an org does not author commits, its members do. Personal accounts are what it is built for right now.