# The Teaching Lab (learn.bztmon.com) A multi-page static technical learning site: scroll-driven teardowns of infrastructure the author actually operates. Dark engineering-dossier aesthetic (void `#070b14`, cyan `#3fbaf5`, magenta `#e879f9`), dependency-light by design, strict security posture. ## Pages | Route | Page | Source | |---|---|---| | `/` | The Teaching Lab - chapter directory | `pilot/index.tpl.html` | | `/cluster` | Chapter 01: The Exploded Cluster - eleven-course container-platform teardown | `pilot/arc.tpl.html` + `pilot/manifest-*.json` | | `/mirror` | Chapter 02: The Mirror - a zot pull-through registry, its failure modes and operations | `pilot/mirror.tpl.html` + `pilot/mirror.js` | ## Build `bash build.sh` -> `dist/`. The assembler (`pilot/assemble-arc.mjs`, plain node, no dependencies) wraps each page in a shared document shell (canonical/OG metadata, build revision, skip link), content-fingerprints every file under `/assets/` (immutable-cached by nginx), splits page scripts into external fingerprinted files, injects intrinsic image dimensions (WebP and JPEG parsed from the actual bytes) with deliberate lazy/eager loading, and runs per-page preflight gates: no inline scripts (CSP `script-src 'self'` with no exceptions), exactly one `h1`, unique ids, no dangling anchors, no unresolved placeholders, and page-specific content assertions. A failed gate fails the build. Ship: `podman build` (multi-stage: node builds `dist/`, `nginx-unprivileged` serves it, both digest-pinned) -> push to the estate registry -> digest-pinned deploy via GitOps. `nginx/` carries the runtime config: strict CSP, HSTS, no-cache HTML with immutable fingerprinted assets, security headers on every location. ## Accessibility and performance Skip link on every page (hidden until keyboard focus), one `h1` per page, stable section anchors, reduced-motion honoured live (effects also pause when the tab is hidden or the scene is off screen), intrinsic image dimensions to prevent layout shift, below-fold images lazy-loaded, system font stacks (CSP permits no third-party fonts). ## Layout | Path | What | |---|---| | `pilot/` | page templates, page scripts, scene manifests, the assembler | | `assets/dist/` | production heroes and diagrams for `/cluster` | | `assets/mirror/` | plates for `/mirror` | | `content/` | course source notes | | `nginx/` | runtime config baked into the image | | `tools/slicer.html` | slice editor: load a hero, tune cut lines, export a scene manifest | | `prompts/` | image prompt contract for the house visual style | | `exploded-cluster.html`, `ec2-part*.html` | v2 (parked, superseded by `/cluster`) | | `gsap.min.js` / `st.min.js` | GSAP 3.13 + ScrollTrigger, fingerprinted at assemble time | ## The slicing rule (load-bearing - read before touching the arc engine) Parts occlude each other in 2D, so every slice carries a hidden notch where the part in front covers it. Animating **collapsed -> hero** only ever increases occlusion, so notches stay buried. **Never overshoot past the hero layout and never fan parts sideways** - either exposes the tears. Region boundaries overlap upward by `EPS`; expanding downward would ghost.