Personal website of Carsten Bokemeyer — hand-written static HTML, no build step, no generator, no runtime JavaScript.
| Page | File | Language |
|---|---|---|
| Start | index.html |
en |
| CV | cv/index.html |
en |
| Imprint & privacy | impressum/index.html |
de |
| Not found | 404.html |
en |
assets/site.css All styling: tokens → shared shell → per-page blocks
assets/fonts/ Self-hosted woff2 + their OFL licences
assets/ Logo, portrait, company logos, favicons, OG image
design/og-card.html Source template for assets/og-image.png — not deployed
site.webmanifest
- Asset paths are root-absolute (
/assets/…). This is required, not cosmetic: GitHub Pages serves404.htmlfor any missing path while the address bar keeps the requested URL, so relative paths would break on the error page. - URLs always carry a trailing slash —
/,/cv/,/impressum/. The same spelling is used in canonicals, Open Graph, the sitemap and internal links. - Fonts are self-hosted. Nothing is loaded from Google or any other third party. The privacy text in the imprint says so — if that ever changes, the text has to change with it.
- Page-specific CSS is scoped by the
bodyclass:page-start,page-cv,page-imprint,page-404. - Copy comes from the design handoff and is authored — don't paraphrase it.
assets/og-image.png (1200×630) is exported from design/og-card.html:
./design/og-export.shIt renders through headless Chrome so the real self-hosted webfonts are used. Never re-typeset the card in an image editor — edit the template and re-run the script, otherwise the image drifts from the site's typography.
The card's footer shows the address the site is served from, so it changes with the domain: edit the template, re-run the script, commit the new PNG.
The site is served from https://carsten-bokemeyer.de. carstenb.github.io
redirects to it, as does www.
There is no CNAME file in this repo, and there must not be one. GitHub only writes one when a site publishes from a branch. This repo publishes from a custom Actions workflow, where any CNAME file is ignored; the domain lives in the Pages settings instead, alongside the source setting "GitHub Actions".
DNS at the registrar (dogado):
carsten-bokemeyer.de A 185.199.108-111.153 (four records)
carsten-bokemeyer.de AAAA 2606:50c0:8000-8003::153 (four records)
www CNAME carstenb.github.io.
_github-pages-challenge-carstenb TXT domain verification, optional
One thing worth knowing if HTTPS ever gets stuck again: the certificate covers
the apex and www together. While www had no DNS record at all, GitHub
could not complete the challenge for that name, so no certificate was issued
for either, and "Enforce HTTPS" stayed greyed out for five days with nothing in
the interface explaining why. Check that both names resolve before looking
anywhere else.
The profile at github.com/carstenb comes from the repo carstenb/carstenb,
which is build output only. Don't edit it there; the next sync overwrites it.
npm run profileprints the README. profile/build.js takes identity from the JSON-LD, and the
claim, topics, Mandoria headline, companies and contact address from
index.html. It also sets the claim as an SVG header in the site's fonts and
colours. profile/README.template.md holds the structure and the copy that only
exists for GitHub. The rule: facts, identity, positioning and reusable content
come from the site; GitHub-specific wording stays in the template.
Extraction is strict. If a markup change leaves it without a claim, topic or
company, the validate workflow fails on the PR. After a merge that touches
any of its inputs, sync-profile-readme.yml builds the profile and mirrors it
into carstenb/carstenb.
The sync needs the Actions secret PROFILE_REPO_TOKEN: a fine-grained token
for carstenb/carstenb only, with Contents: Read and write. It expires. When
it does, the sync fails and the profile stays as it was until a new token is
stored.
Not covered by any automation:
- The
© 2026in the footer of all four pages. - The imprint text (legal content).
- Renewing
PROFILE_REPO_TOKENbefore it expires.
If the domain ever changes again, these move together. design/check.js asserts
most of them, so it will fail loudly on anything missed:
index.html, cv/index.html, impressum/index.html canonical, og:url, og:image
index.html JSON-LD url, @id, image
sitemap.xml both <loc> entries
robots.txt the Sitemap: line
design/check.js the ORIGIN constant
design/og-card.html footer line, then re-export
Outside the repo: the Pages custom domain setting, the DNS records above, and the Search Console property.
The previous Hugo site is preserved at the tag old-site-2021.