canonical vs extras

PLATFORM = "github", CATEGORY = "development".

Card always has contests and rating. GitHub fills them with empty Contests() and Rating(). There are no GET /{username}/contests or GET /{username}/rating routes. CodeTrace’s six-way fetchCard still asks those paths; they 404 here. The client turns a failed section into an empty stub.

Mapper:

Function Mapping
profile_from REST user + social. country is GitHub location
stats_from totalCommits → totalSolved. Languages → topicAnalysis with count = round(percentage). byDifficulty keys commits, optional prs / issues / reviews
heatmap_from GraphQL calendars, then window_heatmap
badges_from scraped profile achievements
summary_from commits + active days

SVG extras for GitHub only: totalStars, currentStreak, longestStreak as {n}d. Label is “Total Commits” / “TOP LANGUAGES”. Accent #3fb950.

Badges are scraped from github.com/{username} because GitHub has no achievements API. HTML scrapes. Full envelope: Envelope and schemas.

First-class extras the coding platforms do not have:

http
GET /{username}/languages
GET /{username}/contributions
GET /{username}/contributions/breakdown
GET /{username}/repos?attributed&full
GET /{username}/stars
GET /{username}/pinned?first=1..6
GET /{username}/star-lists?include_repos
GET /{username}/commits
GET /{username}/profile-views
GET /{username}/me/pulls
GET /{username}/org-contributions
GET /{username}/prs

Playground list in routes/docs.py omits breakdown, pinned, star-lists, profile-views. Those routes still exist.

/{username}/repos?full=true is the heaviest JSON: README, languages, contributors, releases, commit counts, 7.5s deadline. Over budget returns a skeleton. Cache write only if at least one README landed, so a timeout does not poison Redis.

The tashif.codes portfolio fans out /{user}/stats?attributed=true&source=portfolio-own-commits-v2 plus /prs, /stars, /commits, /me/pulls, /org-contributions. That source query is ignored by the API. It is a cache-buster / debug tag on the portfolio side.