nfrs.sgit.ai / admin

Admin & engineering

This site is hand-written static HTML with two build tools and one gate. Nothing is compiled, there is no framework, and a human can open any page and edit it. What is not hand-maintained is the chrome and the version, because a site whose whole argument is about drift should not drift.

One definition of the chrome

admin/build/chrome.py holds the nav, the footer and the version badge, and rewrites them in place across every page in the tree. It also stamps the version into llms.txt, llms-full.txt and index.md, because those were the three places on the sibling sites where a hand-edited version silently went missing.

The pattern is the one the CI page argues for: one source, many consumers, no drift — and applying it here rather than only recommending it is the point.

The pre-release gate

admin/build/validate.js runs before anything is tagged or published, on pushes and on pull requests. A failure stops the release: no tag, no deploy. Five checks:

CheckWhat it catches
Version agreementAny page badge, the versions table, or either text twin disagreeing with version.txt. Also catches a release listed twice, which a blanket version-bump can produce.
Internal linksEvery relative link and source in every page must resolve to a file in the tree.
Canonical hostEvery page must declare where it canonically lives, and it must be on the host in CNAME. This site links twelve siblings, so a canonical left pointing at one of them is the specific mistake worth catching.
Key-leak tripwireNothing in the tree may look like a vault key. The site discusses key discipline; it must never contain one.
The hub's own rulesEvery discipline page must link at least one sibling site, because a page citing nobody has either re-measured or is asserting without provenance. Every page carrying figures must carry an as-of date in a visible marker. These are the two rules this site teaches, enforced on itself.

The last row is small and it is the demonstration behind the freshness-check proposal: the shape works, on sixteen pages. The corpus-scale version is proposed and not built.

The pipeline

Every push to the release branch runs .github/workflows/deploy-pages.yml in three stages, the same pipeline as the sibling repositories:

1

validate

The gate above. Runs on pull requests too, so branch work is checked before it can reach the release branch. A failure here means no tag and no publish.

2

tag-release

Every push to the release branch is a minor release, ending tagged. The version is owned by version.txt, bumped exactly once per release, and it must also appear in the release commit's subject as site vX.Y.Z:. CI verifies the two agree, that the bump is the next minor or a deliberate major, and then tags the release commit — which is the head on a direct push and the head's parent when a pull request lands as a merge. Historical tags are backfilled from commit subjects, idempotently. Three independent statements of the version have to agree before a tag exists.

3

deploy

Publishes the tagged commit to GitHub Pages. Runs on manual dispatch even without a tag, and never when validation failed. Naming is the last step, which is the pattern this site teaches.

The release process

  1. Bump admin/build/version.txt once, and add a row to admin/versions.html. Update comms if the state of play changed.
  2. python3 admin/build/gen_documents.py — only if a source document was added or changed.
  3. python3 admin/build/chrome.py — propagates the version and any nav or footer change everywhere.
  4. node admin/build/validate.js
  5. git commit -am "site vX.Y.Z: …" && git push origin dev

The tree