molecule
Evan — Adom Molecule LED Nameplate
Public Made by Adomby adom
Evan's name in 66 green 0603 LEDs on a 5x7 dot-matrix grid, USB-C powered off the east edge. A real Adom molecule: four corner machine pins, 96x44 mm absolute, every part from the Adom Basic Parts catalog.
← Commit history
Findings: the static export has never rendered inside the wiki sandbox, and why
1 file changed
+64
ADOM-TSCI-FINDINGS.md+64@@ -111,6 +111,70 @@ Two follow-ups: staged bundle for absolute hosts and fail the export on anything that is not same-bundle-relative. +## 3b. The static export has never rendered inside the wiki (the big one)++Every adom-tsci page publishes a viewer whose 3D tab is blank. `alex-nameplate`+has the identical black canvas; I checked it independently before touching+mine. Three separate CSP-driven failures stack up, and **not one of them logs a+console error**, which is why it has gone unnoticed.++The wiki serves README and viewer content under:++```+sandbox allow-scripts allow-downloads allow-popups allow-popups-to-escape-sandbox;+default-src 'none'; script-src 'unsafe-inline' https:; style-src 'unsafe-inline' https:;+img-src data: https:; media-src data: https:; font-src data: https:;+frame-src https:; connect-src 'self' data:; form-action 'none'; object-src 'none'+```++**a. No render loop.** `engine.activeRenderLoops.length === 0`. `scene.render`+is never called, so the canvas never paints — not even `clearColor`. The tell+that costs you an hour: **`engine.getFps()` still returns 60.** Measure real+frames instead:++```js+let n = 0; const ob = scene.onAfterRenderObservable.add(() => n++)+await new Promise(r => setTimeout(r, 1200)) // n === 0 means nothing is drawing+```++Fix: `engine.runRenderLoop(() => scene.render())`.++**b. No lights.** `environmentSpecular.env` fetches fine (200, 273,974 bytes)+but Babylon turns it into a `blob:` URL and `media-src data: https:` refuses it,+so `scene.environmentTexture` stays null. With zero lights every PBR material+renders black. And `Adom3DViewer.BABYLON` exports 15 classes, **none of them a+light**, so userland cannot construct one — invariant #6 in the skill, again.+The only way back in is `Scene.createDefaultLight(true)`.++**c. No framing.** `frameModel()` leaves the camera at radius ~2500 on a 107 mm+board, so even once it renders the board is a speck. Suspect it is framing the+EnvironmentHelper ground plane.++**d. GLB textures.** Same `blob:` problem via `img-src`, and this one DOES throw:+`Unable to load from ./3d.glb: /textures/0: ... blob:null/...`, which fails the+entire GLB load. Externalizing the images to sibling `.png` files does **not**+help — Babylon still blobs a relative URI in a null-origin document. Inlining+them as `data:` URIs is the only form the sandbox accepts. See+`scripts/glb-datauri-textures.mjs` in this project; it rebuilds the BIN chunk+and remaps every accessor, and costs about 8% file size.++**e. The 13 MB bundle.** `render/` 413s over ~4 MB (`{"error":"File too large to+render"}`). Ship 3.5 MB parts, reassemble as **bytes** (a multi-byte character+can straddle a boundary), and inject via `script.textContent` — `script-src`+permits `'unsafe-inline'` but not `blob:`.++**Suggested fix:** fold a `sandboxRenderRescue()` into the static export, guarded+so each repair is a no-op when served normally. There is a working+implementation in this board's `viewer/index.html`. Also worth adding: make the+export emit `data:`-URI textures and split bundles automatically rather than+leaving each board author to rediscover all five.++**One more, unrelated to CSP:** a click-to-load poster cannot be driven by a+synthetic click from outside the sandboxed frame, so it is untestable in a ralph+loop, and it reads as "broken" to anyone who does not realise the still is a+button. An `IntersectionObserver` that loads on scroll-into-view keeps the 15 MB+off first paint and needs no interaction.+ ## 4. `<Molecule>` makes `adom-tsci lint` unsatisfiable With 141 components, tscircuit's schematic auto-layout emits one horizontal