Repository navigation
Replace Hugo site with static pages - #1
Merged
Merged
Conversation
Rebuild the site as four hand-written HTML pages from the design handoff. The Hugo setup is gone: its theme was 100% overridden and never executed, the homepage copy lived in the template rather than in content, and two used APIs (Page.Hugo, Page.URL) were removed in Hugo 0.90. - index, cv/, impressum/, 404 — copy taken verbatim from the handoff - assets/site.css merges foundation.css and the four per-page style blocks; page-specific rules are scoped by body class - fonts self-hosted (4 woff2, latin subset) with their OFL licences, so nothing is fetched from Google — the privacy text says so and now matches reality - <image-slot> scaffolding replaced with plain <img>; the grid cell stays the hover target - accessibility: nav/main/footer landmarks, skip link, visible focus, 24x24 targets, reduced-motion and forced-colors handling - asset and link paths are root-absolute — required because Pages serves 404.html from arbitrary paths - imprint: developer .todo removed, privacy text rewritten for self-hosted fonts, hosting section added - LICENSE.md dropped: it was the Hugo theme author's MIT licence and no longer applies to this content Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Images: - portrait was 311 KB for a 400x600 source; recompressed and served as 200/264/340/400w via srcset+sizes matching the three portrait breakpoints, with fetchpriority=high since it is above the fold - logo-cint 172 KB -> 20 KB, logo-smartrecruiters 92 KB -> 40 KB by downscaling to 400w (they render at ~141px at most) - width/height on every image, loading=lazy on the five company logos Metadata: - robots.txt and sitemap.xml (only / and /cv/ — the imprint is noindex by choice, 404 is never a destination, no unmaintained lastmod) - ProfilePage/Person JSON-LD with a stable @id and sameAs - google-site-verification carried over from the old Hugo head partial - og-card.html now uses the self-hosted fonts and root-absolute paths, so a re-export cannot drift from the live typography og-image.png is left as delivered: it is a text card where JPEG would show artefacts, and only scrapers fetch it, so it costs page performance nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two jobs, deploy-pages gated on needs: validate. Pages must be set to source "GitHub Actions", not "Deploy from a branch" — the branch mode publishes every push regardless of whether the checks passed, which would make the gate meaningless. - design/check.js asserts the site-specific rules generic tools miss: canonical/og:url spelling incl. trailing slash, noindex on the imprint and 404 but not on / and /cv/, no third-party font references, no relative paths (they break the 404 page, which is served from arbitrary paths), every referenced file exists, manifest and sitemap contents, byte budgets - html-validate with void-style/doctype-style off: those flag valid HTML5 self-closing void elements, which is how the handoff wrote them - linkinator for internal links only; external hosts are checked by hand before launch rather than flaking in CI forever - axe over all four pages, Lighthouse over three with the median of three runs so a slow runner does not fail an unchanged site - the artifact excludes design/ and the repo plumbing deploy-pages is skipped, not failed, while vars.PAGES_ENABLED is unset — Pages cannot serve from a private repo on the free plan, so the first run has to be validate-only. Actions are pinned to commit SHAs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The 24x24 touch targets were added with padding alone, which grew the layout boxes: the logo strip card measured 134px instead of the designed 122px and the footer 68px instead of 56px, because the "Full CV" and imprint links each became 12px taller than their line box. Padding still defines the hit area; a matching negative margin cancels its effect on layout. Measured against the handoff reference served side by side, every height now matches exactly: nav 66, logo strip 122, its label row 16, footer 56, CV facts row 41 Hit areas stay above the minimum: Full CV 71x28, footer 135x28, nav 25x30, CV contact links 187x26. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The first run failed on two SEO assertions, both for reasons that were not defects: - /impressum/ scores ~0.61 because it is deliberately noindex. Asserting SEO on a page we ask search engines to skip asserts the opposite of the intent, so that page now gets accessibility, best-practices and performance only. design/check.js already verifies the noindex itself. - /cv/ scores 0.92 on link-text, which flags the nav label "Start" as generic. That word is authored copy from the handoff. Lighthouse judges the visible text, not the accessible name, so an aria-label does not satisfy it — tried and reverted, since it would have added an ARIA override that fixes nothing. Turning link-text off caps the category at 0.92, so the category score alone would no longer catch a real regression. The SEO audits that matter are therefore asserted individually: canonical, document-title, meta-description, http-status-code, is-crawlable, crawlable-anchors, hreflang, image-alt. Verified by running the extracted config through @lhci/cli locally against all three pages: all assertions pass. Whether "Start" should read differently is a copy decision, not a technical one, and is left to Carsten. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All 48 em dashes in the visible copy are gone, replaced by the punctuation each position actually calls for rather than by a different dash. Code comments and the README keep theirs. - page and og titles: "Name | Descriptor", the separator the old Hugo site used as well - image alt: "Carsten Bokemeyer: I build platforms as products, ..." - appositives and trailing qualifiers: comma - lead-ins to a list or an elaboration: colon (side projects intro, small builds, chefkoch.de portfolio, tech organization, EMEA/NAMER/APAC) - the bracketed aside about the Platform & Ecosystem group headcount: real parentheses - talk titles: colon before the quoted title, except "Working Products 2019", whose title already contains a colon — a comma there avoids two stacked colons - education rows: the space before the span was dropped so the colon sits tight against the year instead of reading " : Westdeutsche" - contact paragraph: colon, since the preceding list is a noun phrase and a comma would splice it onto the imperative An en dash was not used: the CV already spells date ranges with it, and reusing the glyph would give one character two meanings. Note: assets/og-image.png still shows the old headline. The template design/og-card.html is updated, but the PNG has to be re-exported at 1200x630 for the two to match. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The social card still showed the em dash headline after the punctuation change. Re-exported from design/og-card.html through headless Chrome, so the real self-hosted webfonts are used rather than a hand-rebuilt image. The card is 1200x630 inside a body with 20px padding, so the shot is taken at 1240x670 and the padding cropped away centred. Result is byte-for-byte the declared size and, at 180 KB, smaller than the 272 KB it replaces. design/og-export.sh captures the recipe: it reuses the local preview server if one is already running, starts one otherwise, and asserts the output dimensions before it finishes. Not changed: the card's footer still reads carsten-bokemeyer.de, which is authored copy and the domain the site is headed for, though not the one it is served from today. Noted in the README. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The card footer read carsten-bokemeyer.de, a domain that currently answers 403 from a different host. Anyone sharing the link today would see a preview naming an address that does not serve this site. It now reads carstenb.github.io. Re-exported with design/og-export.sh, so the PNG and the template stay in step. Layout is unaffected: the string is a similar length and the footer row does not rewrap. This joins the list of things that change together when the custom domain lands — canonicals, og:url and og:image, the sitemap, the JSON-LD @id, the Search Console property, and now this line. Noted in the README. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replaces "Start" in the nav of the CV, imprint and 404 pages. Lighthouse counted "Start" among its generic link texts, and it judges the visible text, so the CI exception that word forced can go: link-text is asserted again and categories:seo is back to a minimum of 1. The German imprint uses "Home" too, for consistency across the nav. Its footer keeps "Zurück zur Startseite" — that is a sentence, not a nav label, and "Zurück zu Home" would be poor German. Also fixes design/check.js walking dot-directories: a local .lighthouseci run left 800 KB report files that the byte budget then flagged as deployed content. Tooling directories are now skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI failed performance on the start page at 0.86/0.85/0.84. It was not runner noise, as I had assumed: CLS was 0.234, well past the 0.1 budget. A real browser showed zero shift because the fonts were cached. Lighthouse measures cold, so the swap actually happens — and only Manrope and Gabarito were preloaded. Caveat Brush carries the headline accent and Space Mono the labels, both above the fold on every page, so they arrived late and reflowed the largest text on screen. All four are now preloaded. They are needed above the fold regardless, so this shifts their discovery earlier rather than adding weight. performance 0.84 -> 0.98 CLS 0.234 -> 0 FCP 1.5s -> 0.9s speed index 1.5s -> 0.9s LCP 2.7s -> 2.4s Verified with the workflow's own config through @lhci/cli across all three audited pages: all assertions pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1. Privacy wording no longer contradicts the hosting section
The old text claimed absolutely that no personal data is collected or
stored, one section after stating that GitHub processes access data,
and it did not cover incoming mail cleanly either. It now scopes the
claim to what I actually control ("beim bloßen Besuch ... erhebe ich
selbst keine"), names GitHub's technically required processing as
unaffected, and covers correspondence explicitly.
Still a draft: the legal text needs Carsten's sign-off before this goes
public.
2. CI tooling pinned to exact versions
The actions were pinned to commit SHAs, but the npx tools floated on
version ranges, so re-running this commit later could validate it with
different tools than it passed with. Added package.json with exact
devDependencies plus package-lock.json; the workflow runs npm ci and
invokes every tool with --no-install, which fails loudly instead of
quietly fetching something newer.
package.json, package-lock.json and node_modules are excluded from the
Pages artifact, and the deploy job now asserts they are absent.
3. Print rule no longer treats the whole history as one block
.roles wraps all five positions and runs to several pages, so
break-inside:avoid on it asked for something impossible. Now only .role
and .row avoid breaking.
design/check.js gained a NOT_DEPLOYED list so the byte budget measures the
artifact rather than the working tree — package-lock.json alone had pushed
the reported total from 795 KB to 1001 KB.
Verified locally with the pinned tools: invariants, html-validate,
linkinator (26 links), axe (4 pages, 0 violations), Lighthouse (9 runs, all
assertions), and the print rules checked by applying the @media print block
unconditionally: nav/skip/contact/footer hidden, .role and .row avoid,
.roles auto, company URLs printed, mailto suppressed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replaces "carry" in the hero line, its two alt-text copies on each of the three pages, and the OG card template — eight occurrences. "carry" is idiomatic English in the sense of sustaining something, but it reads as literal load-bearing to a German ear, and Carsten is the author. "build" was ruled out: the sentence opens with "I build platforms", so repeating the verb flattens the contrast and shifts the meaning from operating to making. "run" is the standard word for operating a system in production and keeps the original sense. og-image.png re-exported so the card matches the page. Headline still sets in three lines, the Caveat Brush accent still sits on "products". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Rebuilds the site as four hand-written static HTML pages from the design handoff, and replaces the Hugo setup entirely.
Why
The site has been offline for years for two independent reasons: the repo is private, and GitHub Pages was never re-enabled (
has_pages: false). On top of thatbaseurlpointed athttps://example.com/, so CSS, JS and favicons on the deployed site resolved to example.com — it was broken before it went dark.Hugo was doing nothing here: the theme was 100% overridden and never executed, the homepage copy lived in the template rather than in content, and two used APIs (
Page.Hugo,Page.URL) were removed in Hugo 0.90.What is here
index.html,cv/,impressum/,404.html— copy taken verbatim from the handoff404.htmlfrom arbitrary pathsdeploy-pagesruns only aftervalidatepassesNot done yet, on purpose
deploy-pagesis skipped viavars.PAGES_ENABLEDThe previous Hugo site is preserved at the tag
old-site-2021.🤖 Generated with Claude Code