1---2name: portfolio-github-pages3description: Build and deploy a personal/academic PORTFOLIO as a single-page STATIC site (no build step) to GitHub Pages via the gh CLI. Use when the user asks for a portfolio, landing page, "pagina de portfólio", professional site, or "site estatico pro GitHub Pages", especially with a theme (astronomy/space is a known good pattern) and with sections revealed on click (accordions/cards). Covers scanning their real repos for truthful content, the single-page anchor layout, the space/glassmorphism design ingredients, and the gh CLI Pages activation gotchas (public-repo requirement, unarchiving, REST API enable).4---56# Portfolio → GitHub Pages (static, single-page)78## When to use9- "criar um portfólio", "página de portfólio", "site profissional", "site estático pro GitHub Pages".10- Any request for a one-page site with anchor navigation and "invisible content shown when clicked".11- This user (pedro) owns several webpage/page/portfolio repos — reuse an existing one when possible.1213## Workflow (ordered)141. **Scan for truthful content first.** Do NOT invent projects. Read their real repos:15 `gh repo list <user> --limit 60`, then `gh api repos/<u>/<r>/readme` to enumerate ALL repos16 (public + private) **without cloning**; read each README for the real stack/description.17 Also mine local vaults for personal facts: `hardcore-life/99 - Meta/INDICE_VAULT.md`18 (PARA structure, course grade), `page/content/pt-br/index.md` (Sobre mim, Instagram19 handle, hobby), `cv/*.tex` (bolsas de pesquisa, ORCID, áreas de interesse). Pull full20 name, Lattes ID, ORCID, Instagram, hobby straight from there. If a brief is uncertain,21 say so — never fabricate. For a "short resumé" of ALL GitHub work, list every repo22 (private ones get a short brief too — no secrets, just what it does).23 For the animated canvas/constellation/SVG-icon build, see the `animated-portfolio-sites`24 skill (it covers that class of technique).252. **Pick or reuse a repo.** If a `portfolio`/`webpage` repo exists and is archived, it must be26 unarchived before push (see references). Clone it, strip any old scaffold (Jekyll, etc.) if replacing.273. **Build a single `index.html`** + `assets/css/style.css` + `assets/js/*.js`. Pure HTML/CSS/JS — NO28 build step, so GitHub Pages serves it directly from root. Put project/research data in a JS file29 (`window.PORTFOLIO_DATA`) so content is easy to edit.304. **Single-page, anchor nav.** One `<section id="...">` per topic (sobre, projetos, pesquisa,31 curriculo, lattes, contato). A fixed top nav with `href="#id"` + `scroll-behavior: smooth`.325. **"Invisible content revealed on click" = accordion / toggle cards.**33 - Cards: `.card` with a `.card__detail` that has `max-height:0; overflow:hidden;` and transitions to34 a fixed `max-height` when `.card.open` is toggled (JS adds/removes the class on click).35 - Accordions: same `max-height` technique inside `.acc.open`.36 - Reveal-on-scroll: `IntersectionObserver` adds `.visible` to `.reveal` elements.376. **Space/astronomy theme (known-good design):**38 - Starfield: `<canvas>` + `requestAnimationFrame`; handle `devicePixelRatio`; twinkle via `Math.sin`;39 respect `prefers-reduced-motion` (draw a static frame instead).40 - Glassmorphism: `background: rgba(...); backdrop-filter: blur(...); border: 1px solid rgba(...)`.41 - Gradient text on the name: `background: linear-gradient(...); -webkit-background-clip: text; color: transparent`.42 - Soft nebulas: large blurred radial-gradient divs, slow `drift` keyframe.43 - Orbital hero: concentric `border-radius:50%` rings rotating (`@keyframes spin`) with small "moons".44 - Fonts: Space Grotesk (display) + Inter (body) from Google Fonts.457b. **Multi-language (PT/EN/ES/FR) with flag selector.** Put ALL UI strings in a JS dict46 `I18N = { pt:{nav:[...], hero:{...}, sections:{...}, about:[...], contactLabels:{...}, footer:...}, en:{...}, es:{...}, fr:{...} }`.47 - Barra: `.lang-switch` with 4 `<button data-lang="pt|en|es|fr">` each an inline SVG flag + label48 (`PT-BR`/`EN`/`ES`/`FR`). On click set `localStorage.lang`, `document.documentElement.lang`,49 apply `data-i18n="chave"` texts, and re-render data-driven cards/contacts/bolsas (they read a `pick(obj,key)`50 helper that falls back to `obj[key]` if no `obj.i18n[lang]`). Keep PT as default.51 - Data objects may carry `i18n:{en:{title,desc,...},es:{...},fr:{...}}` (PLANO: `obj.i18n[lang].title`).52 Make `pick(x,k)` = `x.i18n && x.i18n[lang] && x.i18n[lang][k] ? x.i18n[lang][k] : (x[k]||"")`.537c. **Canvas background — galaxies + bouncing orbs (known-good for this user).**54 - Galaxies: real-ish spirals — a bright core radial-gradient (white→hue→transparent), stars placed along55 `arms` logarithmic-spiral arms (some flagged `dust` = warmer/rgba), slow `g.rot += g.spin` rotation.56 - Orbs: N particles (`vx,vy ~0.5px/frame`, capped speed) that travel straight and BOUNCE off all 4 edges57 (`if (x-r<0){x=r; vx=Math.abs(vx)}` etc.) — calm but visibly bouncing. Each has a pulsing glow.58 - NOTE: this user wants MOUSE REPULSION on the field, NOT attraction. If you add mouse interaction,59 push galaxies AWAY from the cursor (per-galaxy eased offset), don't parallax-pull them.60 - Respect `prefers-reduced-motion` (static frame).617. **Verify locally** (see "Verification" below) BEFORE deploying.628. **Deploy to GitHub Pages** (see references/github-pages-cli.md for exact commands + gotchas).6364## Pitfalls65- **Free GitHub plan: Pages ONLY works on PUBLIC repos.** A private repo returns66 `422 "Your current plan does not support GitHub Pages for this repository."` when you POST /pages.67 Fix: `gh api -X PATCH repos/OWNER/REPO -f private=false` (the static content has no secrets — fine).68- **Archived repos can't receive push or Pages.** Unarchive: `gh api -X PATCH repos/OWNER/REPO -f archived=false`.69- **The UI "Pages" toggle may demand GitHub Pro.** Use the REST API instead (legacy build type) — it works on free.70- **Repo rename redirects pushes** ("This repository moved…") but the push still succeeds; trust the final `master -> master`.71- **Browser-click verification quirk:** the `browser_click` tool sometimes misses a nested `<button>` inside72 an accordion, so the accordion won't toggle and you'll falsely think it's broken. Verify the handler by73 dispatching a real event in `browser_console`:74 `new MouseEvent('click',{bubbles:true}); head.dispatchEvent(ev)` and re-check the `.open` class.75 A real user click works — don't "fix" working code based on the tool's miss.76- **Browser ASSET CACHE across navigations (silent staleness).** The `browser_navigate` tool reuses the same77 page context and caches JS/CSS between `navigate`s in one session — after editing an asset, re-navigating78 still runs the OLD JS (you'll see stale behavior and think your fix didn't land). Two reliable fixes:79 (a) navigate to `about:blank` then back to the URL, or (b) serve on a FRESH port (`python3 -m http.server 81XX`)80 so the asset URL changes and forces a fresh fetch. Always confirm a behavioral fix against a reload-clean page81 before declaring it done. To inspect internals, temporarily expose `window.__test = {…}` at the end of the IIFE,82 verify, then REMOVE it before commit (never ship `__test`).83- **Quartz deploy is async + CDN-cached.** After `git push` to the Quartz repo, the GitHub Pages build takes84 ~1–7 min and the CDN (Varnish) serves stale HTML for a while (`age:` header). Confirm the deploy actually ran85 with `gh run list --repo <u>/<r>` / `gh run watch <id>` and check `gh api repos/<u>/<r>/deployments` — the86 latest deployment `sha` must match your commit. Only then trust a "still shows old content" curl as real.87- 7d. **Sibling Quartz site (this user owns one).** The portfolio is a SHORT RESUMÉ; the official site is a88 Quartz vault (Obsidian) at `www.phrandrade.com` / `pedroiff0.github.io/page` with full content89 (research, classes, media, blog). Cross-link it from the portfolio and add a DISCLAIMER on the portfolio90 that it's a summary (e.g. a `.disclaimer` block with 4 lang spans shown via91 `html[lang=...] .disclaimer .lang-X{display:block}`). When editing the Quartz `content/<lang>/index.md`:92 inline HTML + Obsidian callouts (`> [!abstract]`) compile fine; don't DELETE files from `content/` (the93 Pages deploy has a mass-deletion guard and the Quartz Syncer can wipe drafts); a push just edits index md.94**Keep it KISS.** No framework/bundler for a portfolio; a 3-file static site is more robust on Pages.9596## Verification (ad-hoc, run before declaring done)97- `node --check assets/js/*.js`98- Serve on a FRESH port (`python3 -m http.server 81XX`, background), then `curl -o /dev/null -w "%{http_code}"` for `/`,99 each asset, and finally the published URL (`https://<user>.github.io/<repo>/`) — expect 200.100- Prefer a temp script `/tmp/hermes-verify-<name>.sh` that checks files + `node --check` + data shape + served HTML101 markers, prints PASS/FAIL, and self-removes. Run it; report it explicitly as ad-hoc (not a suite).102- Browser verification: navigate `about:blank`→back (or fresh port) to defeat asset cache before asserting a fix landed.103 Use `browser_console` to read `window.PORTFOLIO_DATA` / dispatch events / measure canvas state when the DOM isn't enough.104- Optional: browser screenshot to confirm visual theme.105- After enabling Pages (or pushing to Quartz), wait for the deploy (`gh run watch <id>`) before curling the published URL.106107## References108- `references/github-pages-cli.md` — exact gh CLI commands + JSON responses for the deployment gotchas.