sharness.ai / admin

How this site is built

Static HTML with no framework, plus a handful of small stdlib-only tools that keep it consistent. Five sections (design, code, evidence, explain, project), each with a markdown hub. Every page with a twin is written in markdown and its HTML is generated from it; the storyboards are generated from JSON; the front page, the mockups and the three project pages (this one, comms, releases) are hand-written HTML. 404.html maps the addresses from before the restructure of 25 Oct 2026 to the new ones, so no stub folders sit at the root. Modelled on the *.sgit.ai sites (nfrs.sgit.ai in particular), using the same pipeline and gate. The conventions are documented at coding.sgit.ai.

The tools

FileJob
tools/version.txtOwns the site version. Bumped exactly once per release.
tools/chrome.pyThe single definition of the nav, the footer and the version badge, rewritten in place across every page. Also stamps the version into llms.txt and index.md.
tools/validate.jsThe pre-release gate: version agreement, internal links, canonical host against CNAME, a vault-key-shaped-string tripwire, and generate or date every number. Any failure stops the release.
tools/gen_pages.pyGenerates each markdown page's index.html from its index.md twin (the design, code, evidence, explain and project sections), which is the source of truth and is served as-is. --check fails CI when any HTML is stale.
tools/gen_articles.pyGenerates /articles/: each article's page and markdown twin, and the index, from the sources in content/articles/. Those sources are in the newsroom's format (front matter, lead figure, the three anchors) so they import into newsroom.sgit.ai unchanged; the gate holds them to it. --check runs in CI.
tools/gen_storyboards.pyGenerates /storyboards/ from content/storyboards/ (one JSON per storyboard, one cast): each storyboard's page, its markdown script, its bundle.json, and the index. The previews (thumb.jpg, og.jpg) are rendered with the storyboards kit's own renderer and committed; --check fails CI when anything is stale or a preview is missing.
tools/validate_storyboards.cjsRuns the kit's own validator (StoryboardFormats.validate from the pinned release, its sha256 checked) over every storyboard: an unknown character, pose, mood or prop stops the release.
project/sources/The source design pack, verbatim. Never edited: corrections go into the next revision of the pack.
tools/gen_sitemap.pyWrites sitemap.xml from the tree, with each page's last commit date.
tools/gen_llms_full.pyWrites llms-full.txt: the agent surface in one fetch.

The pipeline

.github/workflows/deploy-pages.yml, in this order:

  1. validate: runs the gate, the --check of every generator, and the storyboards kit's validator. It also runs on pull requests, so branch work is gated before it reaches the release branch.
  2. tag-release: every push to dev is a patch release (vX.Y.Z+1); every push to main is a minor release (vX.Y+1.0). The version in version.txt must match the release commit's subject (site vX.Y.Z: ...) and be the right bump for the branch against the latest tag. CI then tags the release commit. (Rule set by Dinis Cruz on 24 Oct 2026; before it, dev pushes bumped the middle number.)
  3. deploy: publishes the tree to GitHub Pages. A push to main, or a manual run, deploys without tagging. Never runs when validation failed.

Cutting a release

# 1. bump tools/version.txt, add a row to admin/versions.html
python3 tools/gen_pages.py && python3 tools/gen_articles.py && python3 tools/gen_storyboards.py
python3 tools/chrome.py
python3 tools/gen_sitemap.py && python3 tools/gen_llms_full.py
node tools/validate.js && node tools/validate_storyboards.cjs
git commit -am "site vX.Y.Z: ..." && git push origin dev