Skip to content

Update portfolio: GitHub projects, localized SEO, cleanup, a11y + CI#2

Merged
1816x merged 5 commits into
mainfrom
claude/update-personal-portfolio-3leofc
Jul 19, 2026
Merged

Update portfolio: GitHub projects, localized SEO, cleanup, a11y + CI#2
1816x merged 5 commits into
mainfrom
claude/update-personal-portfolio-3leofc

Conversation

@1816x

@1816x 1816x commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

Several focused passes over the portfolio, plus a CI workflow so main (the branch Vercel deploys to production) can be protected with a required status check.

Changes

1. Public GitHub projects on /work + localized SEO fix — 4ad126b

  • New "Open work on GitHub" section on the Work page listing the 4 public repos as neo-brutalist cards (language swatch, tags, WIP badge, GitHub link), in EN + ES. Copy derives from each repo's own description — nothing invented. Data lives in site.ts → projects; private repos excluded.
  • GitHub wired into the footer, contact panel and Person JSON-LD sameAs.
  • SEO fix: canonical / hreflang alternates and sitemap.xml were built from internal route paths, so every Spanish sub-page pointed at /es/work, /es/about… which 404 (real paths are /es/trabajo, /es/sobre-mi…). Both now derive each locale's real URL via next-intl getPathname, plus an x-default. JSON-LD no longer emits the still-pending role as a hard jobTitle.

2. Prune post-redesign dead code/deps + targeted a11y — 8cb3930

  • Remove unused deps left from the pre-neo-brutalist design (three, @react-three/*, @types/three, framer-motion) and the dead SignatureCanvas stub / visual config / dead i18n keys.
  • Rewrite/trim README, DESIGN_SYSTEM, CLAUDE.md, CONTENT_GUIDE to match the shipped light-only design.
  • a11y: real <h1> on /contact; focus ring visible on royal/ink surfaces; aria-labels on the motion toggle, locale switcher and logo; bump the CardStack 'BASE' label contrast to AA.

3. Correct heading outline across pages + favicon — 9aaef20

  • Section-title chips → <h2> and skipped sub-item levels → <h3> so every route has one <h1> and no skipped levels (Tailwind preflight keeps the chips visually identical).
  • Replace the leftover dark-serif favicon with the neo-brutalist "SR" lockup (cream on ink), matching the header logo and the OG card.

4. CI — 10480ec

  • Add .github/workflows/ci.yml: a checks job (pnpm typecheck && lint && build) and a Playwright e2e job, on PRs to main and pushes to main.

Verification

  • pnpm typecheck && pnpm lint && pnpm build pass locally; CI runs on this PR.
  • Verified on a production server: repos render in both locales, sitemap.xml emits localized URLs, /es/trabajo returns 200 with correct canonical/hreflang, every route has a valid heading outline, and the new favicon renders.

Follow-up (not in this PR — needs the repo owner)

  • Protect main (require the checks status check, block force-push/deletion) in Settings → Branches.
  • Content only Santiago can supply: portrait, Directa case-study copy + screenshots, experience, education, role, Directa year.

🤖 Generated with Claude Code

claude added 3 commits July 17, 2026 18:55
Surface Santiago's public GitHub repositories on the Work page as a new
"Open work on GitHub" section below the featured Directa case study. Four
verified public projects are added to a `projects` array in the single
source of truth (site.ts), with EN/ES copy derived from each repo's own
description — no invented content. Each renders as a neo-brutalist card
(language swatch, topic tags, WIP badge, "View on GitHub" link), and the
GitHub profile is wired into the footer, the contact panel and the Person
JSON-LD `sameAs`. Private repositories are intentionally excluded.

While here, fix two pre-existing SEO defects surfaced by an audit:

- Canonical, hreflang alternates and sitemap.xml were built from internal
  route paths, so every Spanish sub-page pointed at /es/work, /es/about…
  which 404 (the real paths are /es/trabajo, /es/sobre-mi…). Both now
  derive each locale's real public URL via next-intl getPathname and add
  an x-default alternate.
- Person JSON-LD emitted an unverified (pending) role as jobTitle, i.e. a
  hard claim with no "pending" badge; it is now omitted until confirmed.

Also localize two hardcoded Directa strings (the "Gallery" heading and the
case-study meta title) that shipped in English on the Spanish site.

Verified: typecheck, lint and build pass; a production server confirms the
projects render in both locales, sitemap emits localized URLs, and
/es/trabajo returns 200 with correct canonical/hreflang/x-default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGqP6dAJYGsYKiX4TnR5Dh
The site was redesigned from an editorial light/dark theme (Instrument Serif,
next-themes, a react-three-fiber WebGL hero) to a light-only neo-brutalist look
with a DOM CardStack hero. That left dead weight behind. This removes it and
fixes the low-risk accessibility issues an audit surfaced.

Dead code / dependencies (verified unused by grep; build still passes without
them, which proves it):
- Drop unused deps: three, @react-three/fiber, @react-three/drei, @types/three,
  framer-motion; remove the framer-motion optimizePackageImports entry from
  next.config.mjs; prune the lockfile.
- Delete src/components/three/SignatureCanvas.tsx (a null stub with no
  importers) and the empty three/ dir.
- Remove the never-read `visual` (enableSignatureField / preferWebGPU) block
  from site.ts.
- Remove dead i18n keys from both locales: meta.ogAlt, home.heroEyebrow,
  common.theme/themeLight/themeDark/themeSystem/scrollHint/backHome,
  footer.colophonHeading/colophonBody. (Kept the hero* keys CardStack uses.)

Docs drift: rewrite/trim README, DESIGN_SYSTEM, CLAUDE.md and CONTENT_GUIDE so
they describe the shipped light-only neo-brutalist system (no dark mode, no
Three.js, CalmToggle not ThemeToggle) and the real remaining pending items
(WhatsApp/calendar/CV are done; GitHub projects added).

Accessibility:
- ContactPanel takes an `asPageHeading` prop so the /contact route renders a
  real <h1> (it had none — only an <h2>); the home page keeps it an <h2>.
- :focus-visible gets a cream halo so the focus ring stays visible on royal/ink
  dark surfaces where the royal accent outline vanished.
- CalmToggle gains an aria-label (its visible label is hidden below sm).
- LocaleSwitcher's aria-label is localized via common.language.
- Header logo link gets a stable aria-label.
- Bump the CardStack 'BASE' sub-label contrast to full on-accent (was ~4.3:1).

Verified: pnpm install, typecheck, lint and build all pass; a production server
confirms /contact and /contacto each have exactly one <h1>, the home page keeps
one, the locale switcher aria-label localizes, and the focus ring is visible on
the royal contact panel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGqP6dAJYGsYKiX4TnR5Dh
Section titles were rendered as styled "chip" <div>s and some per-item titles
skipped a heading level (h1 -> h3 with no h2; capability groups as h4), so
screen-reader/SEO document outlines were broken. Convert section-title chips to
<h2> and demote/promote sub-item titles to <h3>, keeping page-eyebrow chips (the
ones directly above a page's <h1>) as decorative <div>s. Tailwind's preflight
strips default heading styles, so the tag swaps are visually identical — the
chips render exactly as before.

Files: IntroBlock, WorkPreview, ServicesGrid, CapabilitiesGrid (home sections),
work/page (featured card name), about/page (On Directa / Experience / Education
chips + role/degree items), work/directa/page (Block label + Features + Gallery).
services/page and the contact route were already correct and are untouched.

Favicon: replace the leftover old-design dark-serif "Sr" (icon.tsx) with the
neo-brutalist "SR" lockup — cream on ink — matching the header logo and the OG
card. The OpenGraph image was already neo-brutalist; only the stale MEDIA_PROMPTS
note claiming otherwise is corrected, and its brand-kit blue is aligned to the
real royal token (#2746D0).

Verified: typecheck, lint and build pass; a production server confirms every
route (/en, /es, /en/work, /es/trabajo, /en/work/directa, /en/about,
/en/services, /en/contact) has exactly one <h1> and no skipped heading levels,
the section chips look unchanged, and /icon renders the new favicon.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGqP6dAJYGsYKiX4TnR5Dh
@vercel

vercel Bot commented Jul 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
santiagorivera Ready Ready Preview, Comment Jul 19, 2026 2:17am

Add .github/workflows/ci.yml so pull requests to main and pushes to main run
the documented CI gate — pnpm typecheck && lint && build — plus a Playwright
e2e job. This gives branch protection a required status check to gate merges
into main (the branch Vercel deploys to production); until now the gate only
ran locally.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGqP6dAJYGsYKiX4TnR5Dh
@1816x 1816x changed the title Claude/update personal portfolio 3leofc Update portfolio: GitHub projects, localized SEO, cleanup, a11y + CI Jul 19, 2026
The Playwright config runs two projects — Desktop Chrome (chromium) and
iPhone 13 (webkit). CI only installed chromium, so the mobile project failed
with "Executable doesn't exist ... webkit". Install both engines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGqP6dAJYGsYKiX4TnR5Dh
@1816x
1816x merged commit 0b653d0 into main Jul 19, 2026
4 checks passed
@1816x
1816x deleted the claude/update-personal-portfolio-3leofc branch July 23, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants