Claude-skill-registry github-wrapped
Generate a verifiable GitHub Wrapped year-in-review as a single-file HTML (raw gh API JSON saved, Python-built dataset embedded), with a Bilibili-style narrative, smooth transitions, and mobile-friendly paged mode. Requires gh CLI to be authenticated.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/github-wrapped" ~/.claude/skills/majiayu000-claude-skill-registry-github-wrapped && rm -rf "$T"
skills/data/github-wrapped/SKILL.mdGitHub Wrapped (Single-file HTML, Verifiable Data)
This skill generates a GitHub “Year in Review / Wrapped” as a single self-contained HTML file with a Bilibili-style narrative (scroll/page scenes, cinematic transitions, share card). The non-negotiable requirement is verifiability: every number must be traceable to saved
gh api raw responses committed alongside the report.
Non-negotiables
- No fabricated data: if GitHub APIs cannot provide a metric, show
and explain the limitation in-page.— - Save raw API responses: the report is invalid without a
folder containing the original JSON (and the GraphQL queries used).raw/ - Ship one
: no runtime.html
calls; embed a dataset into the HTML.gh - External CDNs are optional (fonts/icons/screenshot libs/music) but must never break core navigation/rendering if they fail to load.
- Build step-by-step: start with a tiny scaffold (≤ ~400 LOC) and iterate towards a 5k–10k LOC finished report; never try to ship the full “final” file in one pass.
What to ask the user first
(default: current year)YEAR
(default:USER
)gh api user --jq .login- Output language for the page copy (Chinese is usually preferred for CN users; this doc stays English)
- Timezone (default:
for CN users)Asia/Shanghai - Whether to enable a music widget (autoplay may be blocked; must have a user-gesture fallback)
Recommended layout
data/github-wrapped-$YEAR/ raw/ # verifiable gh API responses (JSON) processed/ # dataset.json derived from raw/ frontend/standalone/ github-wrapped-$YEAR.html
Pipeline (raw → dataset → single HTML)
1) Collect raw JSON with gh api
(always paginate)
gh apiPagination rules:
- GraphQL:
--paginate --slurp - REST:
--paginate
Minimum raw set (recommended filenames):
(profile, createdAt)raw/user.json
(GraphQLraw/contributions.json
)contributionsCollection(from,to)
(REST repos list; stars/forks are snapshots)raw/user_repos.json
(GraphQL starred repos ordered byraw/starred_repos_pages.json
, includes topics/language)STARRED_AT
(GraphQL Search: merged PRs in the year; additions/deletions)raw/prs_${YEAR}_pages.json
(GraphQLraw/contributed_repos_pages.json
)repositoriesContributedTo
(optional; REST events; 90-day limit; only for best-effort easter eggs)raw/events_90d.json
Bundled templates (open only what you need):
scripts/collect_raw.shscripts/queries/*.graphqlreferences/data_sources.mdreferences/single_file_engineering.md
2) Build a deterministic dataset (Python, no guessing)
Write a builder that reads only
raw/*.json and outputs processed/dataset.json:
- Deterministic: same raw input → same dataset output.
- Transparent: write limitations into
.meta.dataProvenance.notes[] - Stable for rendering: keep optional fields nullable; avoid breaking changes.
Template:
scripts/build_dataset_template.py
Schema guidance: references/dataset_schema.md
For larger analysis recipes (stars-by-month scatter points, timezone-safe hour buckets, holiday detection, category heuristics), see
cookbook/python/.
3) Embed dataset.json
into the HTML (no runtime fetch)
dataset.jsonYour HTML must contain a stable anchor:
<script id="dataset" type="application/json">{}</script>
Embed rules:
- Always escape
as<
before writing into the HTML.\u003c - If the dataset block is missing/corrupted, the embed script should fail loudly (or repair it).
- The page must show a visible overlay if dataset parsing fails (avoid “cover only, buttons dead”).
Template:
scripts/embed_dataset_into_html_template.py
Step-by-step delivery (400 LOC → 10k LOC)
Single-file cinematic reports get long fast. To stay correct and maintainable, ship in iterations:
- Iteration 0 (contract): agree on a minimal
schema and render placeholders (showdataset.json
for missing fields).— - Iteration 1 (≤ 400 LOC): build the skeleton: cover + “Start”, 2–3 scenes, nav mode toggle stub, dataset parse with a visible failure overlay.
- Iteration 2 (≤ 1.5k LOC): implement the navigation engine (paged/free), reveal system, and a basic card/list system.
- Iteration 3 (≤ 4k LOC): add core charts (heatmap, tower, radar), but keep them simple and verifiable.
- Iteration 4 (≤ 7k LOC): add mobile paged-mode strategy (hide heavy blocks via
+ bottom-sheet that moves DOM nodes).data-mhide="paged" - Iteration 5 (≤ 10k LOC): polish (motion tokens, full-screen HUD, share card, optional music/fireworks), and do a regression pass for desktop + mobile.
Keep this file (SKILL.md) high-level. Put long code samples and analysis recipes into
cookbook/ and implementation notes into references/ to avoid prompt bloat.
Single-file HTML engineering notes (battle-tested)
- Boot layer: always include an explicit “Start” button; do not rely on scroll-only starts.
- Two navigation modes:
(wheel/keys, plus touch swipe on mobile) andpaged
(normal scroll).free - Mobile paged mode: each scene must fit one viewport; hide heavy blocks via
and open them in a bottom-sheet that moves existing DOM nodes (avoid duplicate IDs).data-mhide="paged" - Touch affordances: heatmap tap → toast; radar touchstart → point lift + tooltip.
See
references/single_file_engineering.md for deeper patterns.
Responsive UX (Desktop + Mobile) — hard-won lessons
The page is one file, but it’s effectively two products: desktop cinematic and mobile slide deck. Treat responsive work as surgically isolated changes to avoid regressions.
Desktop (readable without full-screen)
- Prefer a wide-but-bounded content column (
as a--maxw
), and reduceclamp()
slightly on short viewports (e.g. 768px height) instead of shrinking typography.--gutter - Use density variants rather than truncating content:
- Multi-column lists for long leaderboards (keep metadata visible).
- “Dense” list styling (tighter padding/gaps) for better above-the-fold readability.
- Avoid CSS-stretching canvases (radar charts): size canvas from its rendered rect and DPR, or enforce an
and draw in CSS pixels.aspect-ratio - If a 3D/transform section makes buttons unclickable, assume a stacking-context problem first (z-index + transforms + pointer-events).
Mobile (paged-mode = slide deck)
- Gate layout changes with
(width-only rules can accidentally affect small desktop windows).@media (max-width: 620px) and (pointer: coarse) - In mobile
mode, avoid inner scrolling in scenes; hide heavy blocks withpaged
and expose them via a bottom-sheet modal that moves the existing DOM node (so IDs and event listeners remain valid).data-mhide="paged" - Use touch-first affordances: tap feedback (toast), big hit targets, and optionally draggable floating controls (mode toggle / music) respecting safe-area insets.
For implementation patterns (bottom sheet node-moving, draggable HUD controls, canvas DPR sizing, and stacking-context pitfalls), see
references/responsive_ui_patterns.md.
Narrative + UI quality bar (Bilibili-style pacing)
Design as a storyboard: each scene answers one question, then transitions.
Suggested pacing:
- Grand cover + “Start” (cinematic; optional fireworks)
- “How long since we met GitHub” (account createdAt → years)
- “Your 2025 pulse” (activity tier + distribution)
- Heatmap/city + streak + craziest day
- “Time Tower” (12 months; month selector + star-time scatter points)
- “Radar / hexagon” (categories; points lift/glow on hover or touch)
- “New interests unlocked” (2025 stars vs previous years)
- “Extreme moments” (night-owl / holidays; clearly mark best-effort)
- “Open Source Award” (external contribution highlight; award ceremony feel)
- Finale share card (screenshot-friendly; optional fireworks)
Interaction rules:
- Every button/card should be clickable with feedback (links when available; otherwise micro-interaction/toast).
- “Free scroll” vs “Page mode” must behave differently (page mode should snap/lock navigation by wheel/keys, and support touch swipe on mobile).
- Unify motion tokens (duration/easing) across scenes; prefer
.transform/opacity
Known data limits (must disclose)
- Contribution calendar provides day-level counts, not a complete commit list per day.
- Events API keeps only ~90 days of history.
- Repo
are current snapshots, not year-increment.stargazers_count/forks_count - Private contributions / hidden settings can skew the public view.
Debug checklist
See
references/debug_checklist.md for the full checklist. Common root causes:
- A JS parse error stops all handlers (duplicate
, missingconst
)) - A broken embedded dataset block breaks JSON parsing
- A blocked external script was treated as required instead of optional
Bundled resources (progressive disclosure)
: reusable collection/build/embed templates (execute without loading into context)scripts/
: analysis recipes and larger Python snippets (open only what you need)cookbook/
: schema + storyboard + debugging notes (open only the specific file you need)references/