Repository navigation
Gate deploy on CI, strip GPS from headshot, per-page share metadata, blog polish - #132
Merged
Merged
Conversation
… pnpm 12 - deploy.yml calls ci.yml (now a reusable workflow) and builds only after format, lint and build pass, so a push that fails CI is no longer published. ci.yml gets read-only token permissions and PR-scoped cancel-in-progress; the Next cache key now includes .mdx sources. - renovate.json: rebase PRs whenever they fall behind main, group non-major devDependency bumps into one PR, weekly lockfile maintenance, and keep @types/node on the Node 24 runtime. - devcontainer: Node 24 image to match CI; install pnpm via npm instead of corepack (pnpm self-manages to packageManager). README: Node.js 24. - merge-renovate-prs skill: REST equivalents for cloud sessions (gh GraphQL is blocked), pnpm 12 notes, `pnpm update --no-save` replacing the update-then-revert recipe that no longer works on pnpm 12, and the new shape of main's workflow runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0196LghwXY1w3ByYdCGUjWJB
- Headshot: the original 1.4 MB Pixel photo was served as-is (images are unoptimized for static export) with its EXIF GPS location intact. Replace it with a metadata-free 1024px WebP (125 KB) and a 128px avatar (6 KB) for the header, and give it real alt text. - Metadata: pages set only title/description, so every page inherited the root openGraph/twitter objects and shared links previewed as the home page. pageMetadata()/articleMetadata() build canonical URL, Open Graph and Twitter tags per page; posts are og:type article with their own generated card image. OG images are now route handlers exporting real .png files, so GitHub Pages serves them as image/png. - Blog: build-time syntax highlighting (rehype-pretty-code, light/dark), heading anchors, reading time, newer/older post links, no literal backticks around inline code. RSS gains atom:link self and lastBuildDate. - Command palette searches blog posts and shows Ctrl K off Apple devices. - Theme follows the visitor's system setting by default. - CI: check the static export for broken internal links. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0196LghwXY1w3ByYdCGUjWJB
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two commits. The first is repo and workflow fixes from the Renovate backlog clean-up (#125–#131). The second covers site fixes and improvements: a privacy fix for the headshot, correct share metadata for each page, and blog polish.
Repo / workflow changes (first commit)
Deploy is gated on CI
ci.ymlis now also a reusable workflow (workflow_call).deploy.ymlcalls it as acijob, andbuildneeds: ci. Before this, the deploy only built and never ran prettier or lint, so a push tomainthat failed CI but still built was published anyway.ci.ymlno longer triggers onpushtomainitself, so CI doesn't run twice. Onmainit now shows up asci / lint-and-buildinside Deploy Next.js site to Pages.ci.yml:permissions: contents: read. A new push to a PR cancels the PR's in-flight run; calls from the deploy get a unique group, so they never cancel each other.**.mdx, so a blog-post-only change refreshes the cache.Renovate (checked with
renovate-config-validator)rebaseWhen: behind-base-branch: Renovate rebases and regenerates every open PR's lockfile after each merge. Most of the manual lockfile work in the last run was PRs sitting behindmain.dev dependencies (non-major)PR.lockFileMaintenance.@types/nodecapped at<25to match the Node 24 runtime.Node 24 everywhere
typescript-node:5-22-bookworm→5-24-bookworm(the tag exists on MCR). CI and deploy already ran Node 24.npm install -g pnpminstead ofcorepack enable. pnpm switches itself to thepackageManagerversion, and corepack is no longer bundled with newer Node releases.merge-renovate-prsskillgh api) equivalents for Claude Code cloud sessions, wheregh pr …/gh run …fail with a GraphQL 403. Merge withsha=so a Renovate force-push can't slip in an unverified head.package.json→install --no-frozen-lockfilerecipe. It no longer works on pnpm 12 (the lockfile keeps the stale specifier and--frozen-lockfilefails); this is what broke the chore(deps): update react monorepo to v19.3.0 #131 regeneration.pnpm update --no-save <pkg>leavespackage.jsonalone, and I checked that it reproduces chore(deps): update react monorepo to v19.3.0 #131's lockfile byte for byte.main's workflow runs, and agit checkout -- .vs. staged-files gotcha.Testing
pnpm exec prettier --check .,pnpm lint, andpnpm buildpass locally on pnpm 12.15.0.ci.ymlthrough itspull_requesttrigger. Theworkflow_callpath indeploy.ymlonly runs after merge. Watch the first deploy onmainand check that it showsci / lint-and-build→build→deploy, all green.Not in this PR (needs a repo setting)
mainis unprotected. A branch rule requiringlint-and-buildwould stop red PRs from being merged, and would make Renovate automerge for minor/patch bumps safe to turn on later.Site changes (second commit)
Privacy and page weight
app/images/headshot.jpgwas the original 1.4 MB Pixel photo, served as-is because images aren't optimised for static export. It still had its EXIF GPS latitude and longitude. It's replaced by a metadata-free 1024px WebP (125 KB) and a 128px avatar (6 KB) for the header, which loads on every page. Alt text is now "William White at a mountain lake, with a dog in the background" instead of "headshot".Share previews / SEO
titleanddescription, so they inherited the root layout'sopenGraph,twitterandalternatesobjects. Shared links to any page previewed as the home page, linking to/.pageMetadata()/articleMetadata()inapp/lib/metadata.tsnow build the canonical URL, Open Graph, Twitter and RSS alternate tags for every page.og:type=article,article:published_time, and their own generated card at/og/blog/<slug>/card.png..pngfiles. Theopengraph-image.tsxconvention exported an extensionless file, and GitHub Pages picks Content-Type from the extension.Blog
rehype-pretty-code+ Shiki, GitHub light/dark themes), with no client JS.#on hover), reading time, and newer/older links at the end of each post.atom:link rel="self"and a deterministiclastBuildDate(the newest post's date).Other
pnpm check-linksfails the build on broken internal links inout/. I confirmed it catches an injected bad link.Site testing: typecheck, lint, Prettier, build and the link check all pass. I checked the built HTML for each page's og/canonical tags, and confirmed no GPS data remains in the exported images. Playwright screenshots in light and dark mode covered: a post (highlighting on a test Go block, anchors, newer/older links), the blog index, the palette searching posts, and the homepage (only the 6 KB and 125 KB images are requested), with no console errors.
Not done: the resume still lacks the MapLarge role that the homepage and structured data mention. That needs the author's own details.
https://claude.ai/code/session_0196LghwXY1w3ByYdCGUjWJB
Generated by Claude Code