Live at proofstone.dev (noindex, pre-launch)
The umbrella site for the proofstone engineering roadmaps — roadmaps where every node is a milestone you can prove you passed (an artifact), not a keyword.
The roadmap repositories are the source of truth. This repo is the render layer.
Each roadmap's README.md is fetched at build time and rendered into a page. You
contribute to the content by opening a pull request on a roadmap's own repo; the
site rebuilds itself.
Static site: Eleventy → GitHub Pages. No backend, no CMS, no tracking, no cookies.
npm install
npm run dev # fetches roadmap content, then serves at http://localhost:8080
Offline (use already-fetched content in .content/):
npm run dev:offline
Build for production into _site/:
npm run build # SITE_NOINDEX defaults to "true" (pre-launch)
- Add one entry to
roadmaps.config.mjs—slug,repo,branch,title,tagline,status: 'live'. (slug= repo name without the-roadmapsuffix. Milestone count is read from the README automatically.) - Nothing else to write — the fetch step is generic.
- In the roadmap's repo, add
docs/notify-site.yml.tmplas.github/workflows/notify-site.ymlso content edits trigger a site rebuild. The token it needs lives as an organization secret (see How content stays in sync below), so a public roadmap repo needs nothing else. A repo still private for its practitioner review needs its own copy of the secret — on the Free plan org secrets reach public repositories only. - In the roadmap's repo, add
docs/check_form.pyasscripts/check_form.pyand the job indocs/checks-form-job.yml.tmplto its checks workflow. Both files are identical in every roadmap repo. Without them the rules below run only here, after a merge: a contributor's pull request can be green in their repo and break this build the moment it lands. - Generate its social card:
npm run og, then commit the new PNG andog-manifest.json. Skipping this ships a page whoseog:image404s, and the build refuses to pass without a card for every registered roadmap. - Commit and push — the site build fetches and renders it.
The build (.github/workflows/build-deploy.yml) runs on: a push here · a
repository_dispatch fired by a roadmap repo when its README/assets change · a
nightly schedule (safety net) · manual dispatch. Each run re-fetches every live
roadmap, so a content edit lands on the site with no manual steps.
The dispatch needs a credential GitHub does not hand out to a workflow: a job's
built-in GITHUB_TOKEN is scoped to its own repository and cannot fire an event
in another one. So the roadmap repos authenticate with a fine-grained PAT scoped
to this repo with Contents: read & write, stored as the organization secret
PROOFSTONE_DISPATCH_TOKEN. Org-level rather than per-repo on purpose: the same
token was once present in exactly one of four repositories, and the other three
had a dead sync nobody could see.
The two ways this quietly breaks, and what now says so out loud:
- The secret is missing — the notifier fails the run with a named error instead of skipping. A silent skip was tried first and is precisely how three repos ran green with no sync at all.
- The PAT expires — every authenticated response carries a
github-authentication-token-expirationheader, so the notifier prints the remaining days and raises a workflow warning under three weeks.
Neither failure loses content: the nightly schedule still re-fetches everything, so the worst case is an edit landing up to 24h late rather than in seconds.
The site ships with <meta name="robots" content="noindex, nofollow"> on every page
while SITE_NOINDEX is unset or "true". robots.txt intentionally allows crawling
so the noindex tag is seen. /404.html keeps its noindex unconditionally and
declares no canonical, so launching never turns the error page into an indexable
soft-404.
Launching is three steps, not one — changing the repository variable starts no build by itself, so the flip only reaches visitors once a run happens:
- Set the repository variable
SITE_NOINDEXtofalse(Settings → Secrets and variables → Actions → Variables). - Run the workflow: Actions → build-deploy → Run workflow on
main. Without this the change lands whenever the nightly build next runs — up to ~24h later. - Confirm what actually shipped:
npm run verify:live. It walks the sitemap and asserts noindex is gone where it should be, still present on/404.html, robots.txt now advertises the sitemap, and every social card is reachable and numerically matches its page.
This site launched on 2026-07-28, so the launched posture is what verify:live
expects with no flags — an instrument whose default disagrees with production is
one that reports five failures for the sole reason that the launch worked, and
gets ignored accordingly. npm run verify:live -- --prelaunch asserts the other
posture: use it before a first launch, or after deliberately pulling a site out
of the index by setting SITE_NOINDEX back to true and re-running the workflow.
roadmaps.config.mjs # roadmap registry (single source of truth for the site)
eleventy.config.mjs # markdown render: GitHub-compatible anchors, link rewrite,
# milestone/criterion tagging, §-section outline
scripts/fetch-content.mjs # fetch-at-build: README + assets per live roadmap → .content/
scripts/content-guard.mjs # border checks applied to fetched content (shape, markup)
scripts/star-guard.mjs # how a flagship milestone is allowed to render
scripts/check-build.mjs # post-build assertions over _site (runs inside `npm run build`)
scripts/check-guards.mjs # proves the border guards still reject what they must
scripts/check-links.mjs # external link check (advisory, never blocks a deploy)
scripts/make-og.mjs # dev-only: render the 1200×630 social cards + og-manifest.json
scripts/screenshots.mjs # dev-only visual QA (both themes + mobile)
scripts/make-icons.mjs # dev-only: rasterise the SVG mark into PNG icon fallbacks
src/ # templates, data, assets (css/js/icons)
docs/notify-site.yml.tmpl # drop-in workflow for a roadmap repo
docs/check_form.py # the form check a roadmap repo runs on its own pull requests
docs/checks-form-job.yml.tmpl # the CI job that runs it there
The three dev-only scripts (make-og, screenshots, make-icons) drive the
system Chrome through playwright-core (a devDependency; no browser download,
not part of the production build).
npm run build runs the deterministic, offline assertions itself, so they also
guard the autonomous rebuilds fired by roadmap repos: in-page anchors resolve, no
duplicate ids, internal links exist, every map section is clickable, the home page
really shows a milestone, no private repo leaks, and the noindex posture matches
SITE_NOINDEX. npm run check:guards proves the content border checks still
reject bad payloads; npm run check:links probes external links and is advisory
by design — third-party rate limits must never block a content deploy.
Site code: MIT. Each roadmap's content is licensed in its own repository.