-
-
Notifications
You must be signed in to change notification settings - Fork 0
How It Works
Ferran Buireu edited this page Jun 13, 2026
·
3 revisions
ContribKit never touches the GitHub API. It reads the public contributions page that GitHub renders at github.com/users/{login}/contributions, parses the cells out of the HTML, builds a calendar grid, and renders it. No token, no OAuth, no private data.
---
config:
look: handDrawn
theme: neutral
---
flowchart TD
request(["Request"])
middleware["Middleware: rate limit + security headers"]
validate["Validate input (Zod + value objects)"]
usecase["Use case: fetchContributions"]
scrape["Fetch GitHub contributions HTML"]
parse["Parse cells (date, level, count)"]
grid["Build 53×7 calendar grid"]
render["Render SVG (palette, shape, background)"]
respond["Response + cache headers"]
request --> middleware --> validate --> usecase --> scrape --> parse --> grid --> render --> respond
- Middleware applies per-IP rate limiting (100 req/min) and attaches CSP + security headers.
-
Validation parses query/route params with Zod, then constructs domain value objects (
Username,Year). If aUsernameexists, it is valid — invalid input becomes a typedFailurebefore any network call. -
fetchContributions(repo)({ username, year })orchestrates the fetch through the repository interface. - Fetching requests the public contributions HTML from GitHub. See Fetching Contributions.
-
Parsing extracts each day's
date,level(0–4), and exactcountvia regex over the HTML. See HTML Parsing. - Grid building maps the parsed days onto a fixed 53×7 grid aligned to week boundaries. See Calendar Grid.
- Rendering turns the grid into an SVG string using the selected palette, shape, and background. See SVG Rendering.
-
Response is returned with cache headers
public, max-age=3600, stale-while-revalidate=86400(the/api/healthendpoint is the exception:no-store).
Every layer returns T | Failure. A Failure is a typed discriminated union (NotFound, InvalidInput, Network, Parse). At the HTTP boundary, statusFor and messageFor map a Failure to a status code and a user-facing message — the only place that mapping lives. Nothing throws across layers.
| Failure | Typical cause | HTTP |
|---|---|---|
InvalidInput |
malformed username or year | 400 |
NotFound |
GitHub returned 404 for the user | 404 |
Network |
GitHub unreachable or non-OK status | 5xx |
Parse |
HTML structure changed, no cells found | 5xx |
5xx failures are logged to Better Stack with the username, failure kind, and endpoint.
- Architecture — the layers behind this flow
- API Reference — the endpoints that trigger it