An auto-updating landing page for the work of developerfred and aipop-fun. Nothing on it is written by hand: a scheduled GitHub Action crawls the public API, folds every repository into one JSON snapshot, and rebuilds the whole site — page, index, social card and video — from that single file.
- Live: https://developerfred.github.io
- Studio edition: https://aipop-fun.github.io/site (same engine,
SITE_VARIANT=aipop) - Type: Iosevka — subsetted and self-hosted
- Motion: Remotion 4 — one React component, two outputs (live
<Player>in the hero, MP4 in the pipeline)
| Band | What it is |
|---|---|
001 hero |
Kinetic Remotion BuildLog reel playing the last 14 logged events, plus live read-outs |
002 signal |
Instrument panel: repositories, original work, stars, language mix, 21-day activity |
003 index |
A printed datasheet of every non-fork repository — filter by account, language, sort, search |
004 pipeline |
How the page updates itself, the real transcript of the last sync, and the Iosevka specimen |
005 reel |
The rendered MP4 next to the same composition running live in the browser, and both CLI commands |
cron 0 */6 * * * → pnpm sync → src/data/snapshot.json → tsc --noEmit && vite build → GitHub Pages
.github/workflows/deploy.ymlruns on a six-hour schedule, on push, and on demand.scripts/sync-github.mjswalks/users/{login}/reposfor both accounts (18 API calls for 1,234 repositories), reads the public event feed, and writes a ~73 KB snapshot.vite buildrenders everything from that snapshot.vite.config.tsalso injects the meta tags, JSON-LD,sitemap.xml,robots.txtand the styled404.html.actions/deploy-pagespublishes the static artifact. No server, no database, no CMS..github/workflows/reel.yml(weekly, or on demand) re-renderspublic/media/build-log.mp4andpublic/media/og.pngwith Remotion and commits them back.
If the GitHub API is ever unreachable, the sync step is continue-on-error and the build falls back
to the committed snapshot — the site can stale, it cannot break.
pnpm install
pnpm sync # refresh src/data/snapshot.json from the GitHub API
pnpm dev # http://127.0.0.1:5173
pnpm typecheck
pnpm build # tsc --noEmit && vite build
pnpm preview
pnpm verify # screenshots dist/ into out/verify/ via local Chromepnpm sync picks up a token from GITHUB_TOKEN / GH_TOKEN, then falls back to the local
~/.git-credentials entry, then to anonymous (60 req/h — not enough for a full crawl).
pnpm remotion:studio # edit BuildLog / OgCard with a timeline
pnpm remotion:still # OgCard → public/media/og.png
pnpm remotion:render # BuildLog → public/media/build-log.mp4remotion/BuildLog.tsx and remotion/OgCard.tsx are plain React components. The site mounts them
through @remotion/player (lazily, so the 430 KB player chunk never blocks first paint) and the CLI
renders the identical component to H.264.
Iosevka's latin cuts are ~1 MB each. scripts/build-fonts.mjs subsets three weights down to the
ASCII/Latin-1 + interface symbols this page can render using harfbuzz compiled to wasm, taking
2.8 MB → 261 KB. The results are committed, so CI never needs a font toolchain:
pnpm fonts # regenerates public/fonts/*.woff2 and src/styles/fonts.cssIosevka is licensed under the SIL Open Font License 1.1; the full text ships at
public/fonts/OFL.txt.
Both surfaces are the same codebase, switched by one environment variable:
SITE_VARIANT=aipop pnpm build| Variant | Repository | Canonical origin |
|---|---|---|
developerfred |
developerfred/developerfred.github.io |
https://developerfred.github.io |
aipop |
aipop-fun/site |
https://aipop-fun.github.io/site |
deploy.yml derives the variant from github.repository, so the identical workflow publishes the
right brand in each repository — nothing to keep in sync by hand.
Two things worth knowing when wiring a new surface:
- Pages must be set to "GitHub Actions", not the legacy branch build. For a repository literally
named
<user>.github.io, GitHub enables the legacy build automatically, and it will happily publish the raw sources. Check withcurl -H "Authorization: Bearer $TOKEN" https://api.github.com/repos/OWNER/REPO/pagesand switch with-X PUT -d '{"build_type":"workflow"}'if it says"build_type": "legacy". - For a custom domain, set it in Settings → Pages → Custom domain. To also write a
CNAMEfile into the artifact, build withSITE_CUSTOM_DOMAIN=aipop.fun. - If a deployment ever reports
Deployment request failed … due to in progress deployment, the Pages queue is stuck behind a deployment that was superseded mid-flight. It cannot be cancelled through the REST API (the cancel endpoint wants an internal Pages id). Two ways out: cancel it by hand in the repository's Actions UI, or set the repository variablePAGES_PUBLISH=branchand switch Pages → Source to Deploy from a branch: gh-pages.deploy.ymlthen publishes throughpeaceiris/actions-gh-pagesinstead, which never touches the Pages deployments API. That is howaipop-fun/siteis published.
# flip a repository to the branch publisher
curl -X POST -H "Authorization: Bearer $TOKEN" \
https://api.github.com/repos/OWNER/REPO/actions/variables \
-d '{"name":"PAGES_PUBLISH","value":"branch"}'Remotion is free for individuals and small teams; companies above its threshold need a Remotion license — see https://remotion.dev/license.
site.config.ts brand/variant switch (wordmark, copy, origin, accounts)
scripts/sync-github.mjs GitHub API → src/data/snapshot.json
scripts/build-fonts.mjs Iosevka → subsetted woff2 (wasm)
scripts/verify.mjs dist/ → screenshots at desktop + mobile
src/lib/ snapshot types, derivations, formatters, hooks
src/components/ Nav, Hero, Signal, Datasheet, Pipeline, Reel, Footer
src/styles/ tokens, base, generated @font-face
remotion/ BuildLog (video), OgCard (still), Root, fonts.node
.github/workflows/ deploy.yml (cron + Pages), reel.yml (Remotion render)
- Every animation is gated behind
prefers-reduced-motion; the reduced path renders the finished state immediately (count-ups jump to their value, the Marquees and the MP4 stop, reveals are static). - The repository index is a real link list with
role="table"semantics, labelled controls and a skip link; focus rings use the accent colour at 2 px. - Initial payload: ~73 KB gzipped JS + 7 KB CSS + two preloaded font cuts (87 KB each). The Remotion player chunk (125 KB gzipped) is fetched after first paint.
pnpm verifyis the guard rail for layout regressions: it captures the hero, every band and both breakpoints, and fails loudly if Chrome is missing.