跪拜 Guibai
← All articles
Frontend · GitHub

GitHub Archaeology: Input a Username, Get a 71KB Single-File 'Programming Personality' Excavation

By 夏天要喝冰可乐 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Browser-only GitHub tools can skip OAuth, but they hit GitHub's 60-request-per-hour anonymous cap and a canvas taint trap that only fires at export time. The patterns here, degrading optional endpoints, grading errors, and shipping built-in demo data, keep a no-backend app usable when the API says no.

Summary

GitHub Archaeology Lab treats a GitHub account as a dig site. Feed it a username and it pulls the user profile, up to 100 pushed repositories, and public events from unauthenticated API endpoints, then does all the calculations in the browser. The output is a four-part profile: a language 'growth ring' donut chart, scores on night-owl commit hours, naming neatness, language breadth and open-source social reach, and four 'artifacts' such as the oldest repository, the heaviest repo, the most-starred repo, and a naming fossil. The four scores combine into one of 16 personality types with a one-line verdict, and the whole thing exports as a 1080x1440 card with a stamp and topic tags.

The implementation deliberately avoids any backend. It is one 71KB index.html with vanilla JS, no CDN links, no build step, and system fonts. Three public endpoints replace OAuth. Optional event data is wrapped in a catch so a failure only degrades the night-owl score. Errors are graded: 404 means the user does not exist, 403/429 means rate-limited. The unauthenticated GitHub limit of 60 requests per hour gets an offline fallback to a built-in demo profile. The share-card export uses Canvas, which requires setting img.crossOrigin to 'anonymous' before drawing; without it, the canvas is tainted and toBlob throws a SecurityError that hides several lines away from the actual cause.

Takeaways
— GitHub Archaeology Lab calls three unauthenticated endpoints in parallel with Promise.all: user profile, up to 100 repos sorted by push date, and public events; no OAuth tokens are needed.
— All scoring runs in the browser, and nothing is uploaded or persisted; closing the page leaves nothing behind.
— Four dimensions make up the score: Night Owl Index from commit-hour distribution, naming neatness from repo naming discipline, breadth from language count and repo scale, and open-source social from follower and star magnitude.
— Four scores map to one of 16 personality types; the sample account came out as 'Night Excavator, Stratigraphic Chronicler'.
— A sample account with 18 repos showed JavaScript 33%, TypeScript 17%, Vue 11%, HTML 11%, Python 6%, and other 22%.
— Artifact detection surfaces the oldest, largest, most-starred, and worst-named repo; the sample's oldest repo was `untitled-game` from 7 years ago, the largest was 24.2MB, and the most-starred had 86 stars.
— A single 71KB `index.html` makes up the whole product, with zero dependencies, no CDN, and no build step; deployment is one upload and local use is a double-click.
— GitHub's anonymous API cap is 60 requests per hour, so the app maps 403/429 to a wait-and-retry message and falls back to built-in demo data when the API is unavailable.
— Share-card export draws avatars to Canvas, and `img.crossOrigin = 'anonymous'` must be set first; otherwise drawImage succeeds but `toBlob` throws SecurityError.
— Optional public event data gets its own catch; a failure there only drops the Night Owl score instead of taking down the whole profile.
Conclusions

The archaeology metaphor did the information architecture work: repositories became strata, languages became growth rings, repo size became artifacts, and commit times became activity cross-sections, which turned a dull feature list into a story.

A no-backend tool lives or dies by degradation; the separate catch on events, the graded 404/403/429 messages, and the embedded demo profile turn API failures into small gaps instead of a dead end.

Canvas tainting shows how deferred browser API errors can be: drawImage is silent, and the SecurityError appears only at toBlob, so a runnable preview beats reading the docs.

Skipping OAuth and storing nothing is also a product decision: it removes the scary permission screen and keeps the privacy promise short enough for one sentence.

Concepts & terms
Canvas tainting
A browser security state where a canvas element has drawn an image from another origin without CORS permission. The drawing call appears to succeed, but any read or export method such as toBlob throws a SecurityError. Setting img.crossOrigin = 'anonymous' on a CORS-enabled source prevents it.
Unauthenticated GitHub API rate limit
GitHub allows roughly 60 REST API requests per hour per IP address when no authentication token is sent. A client-only app can exhaust this quickly, which is why the tool grades 403/429 errors and falls back to demo data.
Night Owl Index
A score computed from the hour distribution of commit timestamps: the larger the share of commits during late-night hours, the higher the score. It is one of four dimensions in the app's personality profile.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗