-
-
Notifications
You must be signed in to change notification settings - Fork 0
Fetching Contributions
ContribKit gets contribution data by reading GitHub's public contributions page — there is no GitHub API call, no token, and no OAuth. The web implementation lives in infrastructure/github/github-html-contributions-repository.ts and implements the domain ContributionsRepository interface.
https://github.com/users/{login}/contributions
The repository builds the URL, encoding the username and optionally scoping to a year:
- With a
year, it setsfrom={year}-01-01. - If the year is in the past, it also sets
to={year}-12-31(the current year is left open-ended so it tracks "up to today"). - Without a year, GitHub returns the latest rolling year.
The username is always encodeURIComponent-escaped before being placed in the path.
| Request | Resulting URL |
|---|---|
| latest year | .../users/torvalds/contributions |
past year 2022
|
.../users/torvalds/contributions?from=2022-01-01&to=2022-12-31 |
current year 2026
|
.../users/torvalds/contributions?from=2026-01-01 |
GitHub serves this fragment to browser-like clients, so the fetch sends matching headers:
| Header | Value |
|---|---|
User-Agent |
a desktop Chrome UA string |
Accept |
text/html, */* |
Accept-Language |
en-US,en;q=0.9 |
X-Requested-With |
XMLHttpRequest |
Referer |
https://github.com/{login} |
Redirects are followed (redirect: "follow").
The repository never throws. Network and HTTP outcomes are converted to a domain Failure at the boundary:
| Condition | Result |
|---|---|
fetch throws (network error) |
network(message) |
404 |
notFound(username) |
| other non-OK status | network("GitHub returned <status>", status) |
| OK but no cells parsed | parse("Could not parse contributions") |
| OK with cells | ContributionCalendar |
A successful result is { username, days, total }, where days are the parsed ContributionDays and total is the summed yearly count (or null).
- No token required — the GraphQL contributions API needs an authenticated PAT; the public page doesn't.
- Only public data — exactly what's already visible on a profile.
- One place to update — if GitHub changes the page structure, only this module (and its regexes) change. See HTML Parsing.
The Flutter app has its own implementation (infrastructure/github/contribution_repository_impl.dart) following the same idea.
- HTML Parsing — how cells and counts are extracted
- Calendar Grid — how parsed days become a grid
- Troubleshooting — when fetching fails