Agent Skills: GitHub Wrapped (Single-file HTML, Verifiable Data)

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.

UncategorizedID: acking-you/myclaude-skills/github-wrapped

Skill Files

Browse the full folder contents for github-wrapped.

Download Skill

Loading file tree…

skills/github-wrapped/SKILL.md

Skill Metadata

Name
github-wrapped
Description
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.

GitHub 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 raw/ folder containing the original JSON (and the GraphQL queries used).
  • Ship one .html: no runtime gh calls; embed a dataset into the HTML.
  • 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

  • YEAR (default: current year)
  • USER (default: gh api user --jq .login)
  • Output language for the page copy (Chinese is usually preferred for CN users; this doc stays English)
  • Timezone (default: Asia/Shanghai for CN users)
  • 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)

Pagination rules:

  • GraphQL: --paginate --slurp
  • REST: --paginate

Minimum raw set (recommended filenames):

  • raw/user.json (profile, createdAt)
  • raw/contributions.json (GraphQL contributionsCollection(from,to))
  • raw/user_repos.json (REST repos list; stars/forks are snapshots)
  • raw/starred_repos_pages.json (GraphQL starred repos ordered by STARRED_AT, includes topics/language)
  • raw/prs_${YEAR}_pages.json (GraphQL Search: merged PRs in the year; additions/deletions)
  • raw/contributed_repos_pages.json (GraphQL repositoriesContributedTo)
  • raw/events_90d.json (optional; REST events; 90-day limit; only for best-effort easter eggs)

Bundled templates (open only what you need):

  • scripts/collect_raw.sh
  • scripts/queries/*.graphql
  • references/data_sources.md
  • references/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)

Your HTML must contain a stable anchor:

<script id="dataset" type="application/json">{}</script>

Embed rules:

  • Always escape < as \u003c before writing into the HTML.
  • 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 dataset.json schema and render placeholders (show 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 data-mhide="paged" + bottom-sheet that moves DOM nodes).
  • 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: paged (wheel/keys, plus touch swipe on mobile) and free (normal scroll).
  • Mobile paged mode: each scene must fit one viewport; hide heavy blocks via data-mhide="paged" and open them in a bottom-sheet that moves existing DOM nodes (avoid duplicate IDs).
  • 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 (--maxw as a clamp()), and reduce --gutter slightly on short viewports (e.g. 768px height) instead of shrinking typography.
  • 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 aspect-ratio and draw in CSS pixels.
  • 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 @media (max-width: 620px) and (pointer: coarse) (width-only rules can accidentally affect small desktop windows).
  • In mobile paged mode, avoid inner scrolling in scenes; hide heavy blocks with data-mhide="paged" and expose them via a bottom-sheet modal that moves the existing DOM node (so IDs and event listeners remain valid).
  • 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:

  1. Grand cover + “Start” (cinematic; optional fireworks)
  2. “How long since we met GitHub” (account createdAt → years)
  3. “Your 2025 pulse” (activity tier + distribution)
  4. Heatmap/city + streak + craziest day
  5. “Time Tower” (12 months; month selector + star-time scatter points)
  6. “Radar / hexagon” (categories; points lift/glow on hover or touch)
  7. “New interests unlocked” (2025 stars vs previous years)
  8. “Extreme moments” (night-owl / holidays; clearly mark best-effort)
  9. “Open Source Award” (external contribution highlight; award ceremony feel)
  10. 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 stargazers_count/forks_count are current snapshots, not year-increment.
  • 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 const, missing ))
  • A broken embedded dataset block breaks JSON parsing
  • A blocked external script was treated as required instead of optional

Bundled resources (progressive disclosure)

  • scripts/: reusable collection/build/embed templates (execute without loading into context)
  • cookbook/: analysis recipes and larger Python snippets (open only what you need)
  • references/: schema + storyboard + debugging notes (open only the specific file you need)