Hosting
GitHub repository, the build workflow and Cloudflare Pages.
The repository
Everything is in one public GitHub repository, unclehowell/cedwyn.
| Branch | Holds |
|---|---|
main | The 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 section | That section's static site and data (for example wayback, maps, section/research). |
agents | The machine-facing academy at /academy/ (not a section). |
library | This library at /library/ (not a section). |
site | The 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.
- Fetch the tip of every section branch named in
themes.json. - Assemble (
tools/assemble.py): copy each section's output folder todist/<id>/. A section withsnapshot_branchis read at the commitsections.lockpins. A few sections are still copied by a read-only crawl of their live origin. - Rewrite (
tools/rewrite.py): old subdomain links become/<id>/paths; every external link goes to the archive interface; shared files go to/_blob/. - Site root (
tools/site.py): shared header and menu (generated fromthemes.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). - Self-contained pass (
tools/selfcontain.py): every asset served from this site; the build fails on any reference to another host. - Catalogue database (
tools/build_db.py) and the export (tools/db_export.py). - Guards: outbound-link test (
tools/check_links.py), self-contained test, internal-link audit. - Publish to branch
site; build reports are committed tomainunderreports/.
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
mainchanges every section, so it must carry the labelsite-wide(thescope-maincheck fails without it). - A push to
section/<id>passes a scope check (itssection.jsonid matches, no workflow files, no other section inside), thensections.lockis updated and a build starts. - No force-pushes. Roll a snapshot section back by pointing its
sections.lockline at an older commit.