Adom Wiki
Public Made by Adomby adom
How the Adom Wiki (wiki.adom.inc) works and how to drive it with the adom-wiki CLI: the two storage layers (git page repo vs package registry), hosting source by pushing files (not a tarball), making packages, cutting per-platform releases, and the three-tier skill layout (user skills ship, dev-skills/ and publish-skills/ stay source-only). adom-wiki is the current tool; adompkg is deprecated. Read this first before publishing or installing.
readme.html sandbox: lint for the 5 silent traps (storage, 4MB cap, blob:, relative paths, height) + inject the storage shim platform-side
Problem
readme.html is now the way rich pages are built, and the sandbox it renders
in breaks a predictable, finite set of things. Every one of them fails
silently: no console error, no lint warning, and a page that looks fine to
the author locally renders blank or broken once published.
The knowledge exists — issues #47, #60, #134, #135 each cover a piece — but it
is spread across closed issues and one project's skillpack, so each new author
rediscovers it from zero. Concretely: every adom-tsci board page currently
ships a permanently blank 3D tab, and I burned over an hour today
re-deriving the cause of #60 before I found #60.
This is about to get worse, not better: component pages are moving to
readme.html with embedded viewers and applets, so the same five traps are
about to be hit by people who are not debugging 3D engines.
Ask: repo push / pkg lint already emit good advisory hints
(README_HTML_REGISTERED, HERO_ASPECT, broken_images). Extend that with
checks for the sandbox traps. They are all cheap static checks on files the
linter already has in hand.
Versions: adom-wiki 1.7.4 · adom-tsci 1.4.24 · evidence from
adom/evan-led-nameplate.
Proposed checks
1. Unguarded storage access — highest value.
Grep readme.html and any first-party .js it ships for
localStorage/sessionStorage not wrapped in try/catch. In a sandboxed
null-origin document the property read itself throws SecurityError, and a
typeof window !== "undefined" guard does NOT help — window exists, the
origin is null. If that throw lands in an un-awaited async init, everything
after it is silently abandoned.
Measured, published page, cold profile:
lights: 0, environmentTexture: false, activeRenderLoops: 0, getCamera(): null
→ after an in-memory shim, unchanged otherwise:
lights: ["light","spotLight"], environmentTexture: true, activeRenderLoops: 1.
SANDBOX_STORAGE: readme.html or js/foo.js reads localStorage without a try/catch. A sandboxed readme has a null origin and the read throws SecurityError. Shim both storages before your bundle loads.
2. Files over the render cap.
render/ 413s over ~4 MB with {"error":"File too large to render"}. A
<script src> cannot surface that; it just fails. Flag any pushed file over
the cap that the readme references.
RENDER_SIZE_CAP: viewer/js/app.min.js is 13.0 MB; /render/ refuses over ~4 MB. Split it and reassemble client-side.
3. blob: usage against the CSP.
img-src/media-src/script-src allow data: and https: but not blob:.
Any URL.createObjectURL in shipped JS is a likely runtime CSP refusal.
Bites harder than it sounds: Babylon's glTF loader blobs embedded GLB textures,
which throws and fails the whole model load, and the obvious fix
(externalise the images to sibling .png files) does not work either, because
a relative URI still gets blobbed in a null-origin document. data: URIs are
the only accepted form.
4. Relative asset paths in readme.html.
Anything not absolute under https://wiki.adom.inc/<owner>/<slug>/render/…
will not resolve. Trivially detectable, currently discovered by seeing broken
images on a published page.
5. Missing readme-height postMessage.
If readme.html contains no postMessage({type:'readme-height'…}), everything
below the fold is unreachable. The hint text already explains this beautifully
— but only after the push succeeds. Make it a pre-flight check.
6. @font-face in readme.html.
adom.inc font files fail CORS from a null origin every load. One-line grep.
7. .glb orientation on hardware pages.
The wiki's native 3D viewer is Z-up; glTF is Y-up by spec and that is what
tscircuit emits. Publishing an unrotated board.glb stands the board on edge
like a wall, which looks like a modelling mistake rather than a convention
mismatch. The thin axis of a board-like mesh is detectable from the bounding
box.
GLB_ORIENTATION: board.glb has its thinnest axis on Y (Y-up). The wiki viewer is Z-up and will render it edge-on. Bake a +90° X rotation.
Two non-lint asks
A. Inject the storage shim into the readme frame yourselves. The wiki controls the frame wrapper. A no-op storage shim injected ahead of author content would fix every existing broken page at once, with zero author effort, and remove trap #1 permanently. This seems strictly better than asking every author to remember it.
B. Document the sandbox contract in one place.
The README_HTML_REGISTERED hint is genuinely excellent and covers height,
connect-src and the lightbox. Adding storage, the size cap, blob:, absolute
render/ paths and @font-face to that same hint would put the whole contract
in front of the author at exactly the right moment.
Happy to help write the check implementations or test them against
adom/evan-led-nameplate, which now exercises every one of these.