Cedwyn library

Hosting

GitHub repository, the build workflow and Cloudflare Pages.

The repository

Everything is in one public GitHub repository, unclehowell/cedwyn.

BranchHolds
mainThe shell only: section registry themes.json, build tools in tools/, shared runtime in web/_cedwyn/, shared data in data/, sections.lock, workflows.
one branch per sectionThat section's static site and data (for example wayback, maps, section/research).
agentsThe machine-facing academy at /academy/ (not a section).
libraryThis library at /library/ (not a section).
siteThe assembled output that the host serves. Written only by the build.

The build (GitHub Actions)

Workflow .github/workflows/build.yml (job build-cedwyn) runs on a push to main, after a section push through sections-ci.yml, or on demand. A full build takes about 30 to 45 minutes.

  1. Fetch the tip of every section branch named in themes.json.
  2. Assemble (tools/assemble.py): copy each section's output folder to dist/<id>/. A section with snapshot_branch is read at the commit sections.lock pins. A few sections are still copied by a read-only crawl of their live origin.
  3. Rewrite (tools/rewrite.py): old subdomain links become /<id>/ paths; every external link goes to the archive interface; shared files go to /_blob/.
  4. Site root (tools/site.py): shared header and menu (generated from themes.json), runtime, landing page, glossary and name links, footer, the pass that keeps pages from explaining themselves (tools/quiet_pages.py) and the developer library (tools/library_pointer.py).
  5. Self-contained pass (tools/selfcontain.py): every asset served from this site; the build fails on any reference to another host.
  6. Catalogue database (tools/build_db.py) and the export (tools/db_export.py).
  7. Guards: outbound-link test (tools/check_links.py), self-contained test, internal-link audit.
  8. Publish to branch site; build reports are committed to main under reports/.

Cloudflare

Cloudflare Pages serves branch site as static files on the custom domain. DNS is on Cloudflare; the former subdomains answer with a permanent redirect to their /<id>/ path. A few sections with live features (FCG, Ask the Archive, the Case Office, the email search) run a Cloudflare Worker at their own origin; the static site carries a snapshot of each. Free-plan limits that shape the design: 500 builds a month, 20,000 files per deployment, 25 MB per file, and a daily Workers request quota. Static files do not use the Workers quota.

Change rules

  • A pull request into main changes every section, so it must carry the label site-wide (the scope-main check fails without it).
  • A push to section/<id> passes a scope check (its section.json id matches, no workflow files, no other section inside), then sections.lock is updated and a build starts.
  • No force-pushes. Roll a snapshot section back by pointing its sections.lock line at an older commit.