stainlu/codewar
Summary
Codewar is a Cloudflare Workers-based service that generates embeddable SVG charts comparing GitHub contribution activity across up to 5 users over configurable time ranges. It uses GitHub's GraphQL API to fetch contribution data, renders hand-drawn aesthetic SVG charts server-side with an embedded Virgil font, and also generates PNG screenshots via Cloudflare Browser Rendering (Puppeteer) for Twitter/OG card previews. Zero authentication required from users — only a single GitHub token on the server side.
Great for
building GitHub profile readme widgets and social-sharing developer tools on Cloudflare's edge infrastructure
Easy wins
- +Add tests — there are literally zero tests in this project; even a simple smoke test for renderChart() or the smoothing functions would be a meaningful contribution
- +Add a CONTRIBUTING.md and CI workflow (GitHub Actions for type-checking with tsc --noEmit) since has_ci and has_contributing_guide are both false
- +Fix the cache key bug in fetchUserContributions: it caches per-username without the range parameter, so a '3m' fetch caches stale data for a subsequent 'all' request from the same user
- +Add rate limiting or request validation to prevent abuse of the /api/png endpoint which spins up a full Puppeteer browser instance per uncached request
Red flags
- !Cache key bug: fetchUserContributions caches by username only, ignoring range — a cache poisoning scenario where a '1m' request caches limited data that then gets served for 'all' range queries
- !No input sanitization beyond basic username splitting before passing to GitHub GraphQL — usernames are passed directly as GraphQL variables which is safe, but the SVG output does call escapeXml() inconsistently (used on usernames in labels but the avatar base64 URLs are embedded raw)
- !The /api/png endpoint creates a Puppeteer browser instance and loads a remote SVG URL (hardcoded to codewar.dev) — this means self-hosted instances will screenshot the production site, not themselves, unless the HTML template is changed
- !Single GitHub token for all users with no rate limit handling — a surge of requests will exhaust the token's rate limit with no backoff or error surfacing beyond a generic GraphQL error
- !font.ts contains a 50KB+ base64-encoded WOFF2 blob inline in source — not a security issue but makes the file effectively unreviewed/uneditable and bloats git history
Code quality
The TypeScript is clean, properly typed, and well-structured — good separation between chart rendering (chart.ts), data fetching (github.ts), smoothing (smoothing.ts), and the Worker entry point (index.ts). However, there's a real caching bug: fetchUserContributions caches contributions keyed only on username (contributions:${username}), but the range-based year filtering happens AFTER the cache lookup, meaning a cached 'all' result is returned even when only '3m' was requested and vice versa. The PNG endpoint has no concurrency protection — burst traffic could exhaust Cloudflare Browser Rendering sessions. The site/app.js frontend is plain vanilla JS with no bundling, which is fine for its size but inconsistent with the TypeScript backend.
What makes it unique
This is genuinely distinct from star-history.com (which it credits as inspiration) by focusing on contribution counts rather than star growth, and the embeddable SVG-in-README angle with zero user auth is a real differentiator. The hand-drawn Excalidraw aesthetic is a nice touch. That said, the core concept — GitHub stats card for READMEs — is a well-trodden space (github-readme-stats, github-contribution-chart, etc.). The Cloudflare Workers + KV + Browser Rendering stack is a reasonable modern choice for this use case.
Scores
Barrier to entry
lowThe codebase is tiny (~6 source files, <1000 lines of meaningful TypeScript), self-hosting requires just a GitHub token and a Cloudflare account, and the architecture is straightforward Worker routing with no framework magic.