# org - The mrly.net site: the demos that draw MrlyMath, the papers, the research pages, a blog and an about page, every route static HTML. - Rust is the only math; the pages only draw. React renders the demo pages, Three.js draws the 3D; no other dependency. - `bun install` fetches them; `bun run wasm` builds `pkg/` from `crates/mrlydemo` with wasm-pack. - One demo is one folder: a thin `demos//index.html` shell plus `demos//index.jsx`; the gallery is `demos/index.html` + `demos/index.jsx`. - A demo registers nowhere: the folder is the list, its `` is the title, its `description` meta is the blurb, and its `shelf` and `order` metas place it on a shelf; adding a folder adds a route, a tile and a tree node. - A demo's reading list is derived, never declared: every note, paper and wiki page that links or embeds `demos/<name>/` is injected into that demo's head as `<script type="application/json" id="mrly-reads">`, and `Page` in `app.jsx` prints it as one Read line under the foot. - The eight shelves are the `shelves` block in `site.json`, `key`, `group`, `title` and `blurb` each; the build groups the demos by them into `demos/tree.json` and injects that same JSON into every demo head as `<script type="application/json" id="mrly-tree">`, which `tree.js` reads for the header tree and the gallery, falling back to fetching the file in dev. - `lib/` holds the shared code: `mrly.js`, `app.jsx`, `tree.js`, `draw.jsx`, `select.jsx`, `stage.jsx` + `stage.js`, `chart.js`, `series.jsx`, `query.js`, `md.js`, `mrly.css`; `series.jsx` is the sequence-view kit, `Pins`, `Staircase`, `Digits`, `Ratios`, `Differences` and the `Terms` ribbon, so no page prints a bare comma list. - The demo gallery draws no thumbnails: every tile is the demo's figure pair, `demo-<name>-dark.png` and `demo-<name>-light.png`, and the demos route ships them. - The chrome is the kit in `kit/ui` and its README is the reference for it: the header glyphs, the three columns, the drawers, the menu and the settings read from `site.json`, and the footer is one screen, the wordmark held by the pixel-font animation over a copyright line, with no links; `app.jsx` wraps its `Shell` as `Page` beside `mount`, `Row` and the controls, `tree.js` fills the site tree from the injected demo shelves plus the papers, research and blog lists, and `mrly.css` imports the kit and keeps only demo rules; `draw.jsx` wraps every canvas: `Grid`, `Signs`, `Pixels`, `Sketch`, `Markup`. - `Signs` is the plus-minus primitive: a warm hue for plus one, a cool hue for minus one, and the dark ground for empty. - `select.jsx` is the one picker: design list, code, base and Randomize; `?seed=7` replays the seventh tap, and a typed code drops the seed. - `useQuery` in `query.js` keeps page state in the URL, so every view is a link. - Words live as markdown: `blog/<slug>.md`, `../research/papers/<slug>.md` and every `pages/<slug>.md` open with a `---` front matter block (title, date, lead, optional figure naming a file in `files/figures/`); one page file is one route, `/<slug>/`; `public/` copies straight to the site root. - The widget line: a wiki page writes `![caption](demos/<name>/<view>)` on a line of its own and the build mounts that view in place; `demos/<name>/widget.jsx` exports the view as a component named `<view>` and calls `embed('<name>', { <view> })` from `lib/widget.jsx`, which mounts every `figure.widget[data-demo]` on the page; the page loads `/demos/<name>/widget.js`, an entry of the demos' one `Bun.build` call, so a widget shares the React and wasm chunk every demo loads; a widget line naming a missing file or view fails the build. - `../wiki/<slug>.md` is the wiki input: front matter `title`, `lead`, `prerequisites` (wiki slugs, comma-separated) and an optional `figure` (default `wiki-<slug>`); `/wiki/<slug>/` renders one concept page opening on its figure, its prerequisites above the prose and the pages that need it under Read next; a prerequisite with no page or a circle of prerequisites fails the build. - `/wiki/` is the prerequisite graph: one section per depth, Start here for the pages that need nothing, then one step in, two steps in, each tile carrying its figure, its lead and the pages it comes after; `/book/` is the same pages in that order on one page, each chapter opening on its figure with its headings demoted one level, and it is written by nothing but the wiki files. - `bun run dev` renders on request: it scans once, watches every declared input and template, and renders the route you ask for; nothing is prebuilt and `dist/` is never read. - In dev the kit and the figures are served straight from disk and the demos keep Bun's HTML routes, so a CSS or markdown edit shows on the next refresh with no build. - `bun run build` writes the whole site to `dist/` with `scripts/site.ts` alone: pure bun, no Chrome, no cargo, no Python; `bun run clean` empties `dist/` by hand when you want a cold start. `MRLY_DIST=/some/dir` writes there instead, manifest included, so two builds never share a folder. - The demos are one route: one in-process `Bun.build()` over `demos/index.html` and `demos/*/index.html`, its SEO head injected before the shells are written, fingerprinted over `demos/`, `lib/`, `pkg/` and the kit. - That one call splits by use, and the split is load-bearing: React and the wasm glue land in one shared chunk every demo imports, Three.js in its own chunk only the 3D demos import, and a demo's own code in a chunk of a few KB; chunk names are content hashes served immutable, so a reader downloads React once for every demo until React itself changes. Keep `splitting: true` and the hashed `chunk` naming in `scripts/site.ts`; without them every demo ships its own React. - A second `bun run build` renders nothing: every route is fingerprinted into `.cache/manifest.json` with the files it wrote, and dead outputs are deleted by that record. - Two inputs are made on the desk and read at build time: `pkg/` from `bun run wasm` and `../files/figures/` from `bun run figures` (the `figures` crate on the `mrlyfig` kit); every figure is a pair, `<name>-dark.png` and `<name>-light.png`, the page carries both as `img.dark` and `img.light` and the theme shows one; a missing half throws while its own route renders and names the route. - Figures are named by route: `research-<page>`, `paper-<slug>`, `blog-<slug>`, `wiki-<slug>`, `site-home`, `site-wiki`, `site-demos`, `site-papers`, `site-research`, `site-tools`, `site-math`, `site-contact`, `site-donate`, `demo-<name>` and `site-og` (1200x630); a research or blog page opens on its square figure, a markdown page opens on the one its front matter names, a paper page opens on its avatar, the cards and the doors use the same files. - `scripts/shelf.ts` fetches the paper shelf from GitHub into `data/shelf/` at every build and falls back to the cached copy offline; `SHELF_REPO=owner/repo` names the shelf and unset means no fetch, `MRLY_SHELF=/path/to/research` reads a local checkout instead, which `bun run dev` and `bun check.ts` both fall back to, so a rescan never waits on the network and the paper lane is always checked. - Routes: `/`, `/wiki/`, `/wiki/<slug>/`, `/book/`, `/demos/`, `/demos/<name>/`, `/papers/`, `/papers/<slug>/`, `/research/`, `/research/<name>/`, `/research/discoveries/`, `/blog/`, `/blog/<slug>/`, `/tools/`, `/math/`, `/menu/`, `/about/`, `/contact/`, `/donate/`, `/cart/`, `/git/...`, `/raw/...` and `/404.html`, beside `sitemap.xml`, `robots.txt`, `llms.txt`, `manifest.webmanifest` and the icons the builder draws from the logo. - Home is the front door: five doors to `/wiki/`, `/demos/`, `/research/discoveries/`, `/papers/` and `/research/`, the mission line, the newest dated claim read out of `research/claims/`, the three latest papers and the latest post. - `/tools/` is the `thin` kind, one landing with its figure and a line on what is coming, held for the tools plan to fill; `/math/` is the `math` kind and renders `crates/mrlymath/NAMES.md`, the naming standard, under its own lead, so the page and the crate can never disagree. - Every page carries its own figure as `og:image`, the dark side at its real pixel size: a note, paper, post or demo its figure, an index its door, a code page `site-code`, and only `/menu/`, `/cart/`, `/blog/`, `/404.html` and a markdown page without a figure fall back to `og.png`. - `/menu/` lays the whole navigator out with the kit's `Menu` as a figure grid, one picture tile per route with its blurb, closing on an `Elsewhere` list of the socials and the contact address; `/cart/` is a placeholder and, like `/404.html`, stays out of the tree and out of the sitemap. - `bun run shots` serves `dist/` itself, drives one headless Chrome on one port with one throwaway profile, and writes ten full-page pngs, five routes at phone and desktop, into `data/mrlyprod/site/scripts/shots/latest/`, killing Chrome at the end; routes as arguments replace the five, `--print` emulates print media, `--js <expr>` prints an expression per shot, `--baseline` keeps a set to compare later runs against by hash; every canvas but the footer mark is blanked and reduced motion is emulated so a shot is byte-stable, and a shot names the widest elements when a page overflows. - Delivery: the kit's CSS and JS ship under hashed names (`/ui/chrome-1a2b3c4d.js`) and are served immutable for a year, as are the demo chunks and the wasm; `fonts/` and `seti/` keep their names because their CSS names the faces by relative url, and every HTML page, figure and text file goes out at `max-age=0, must-revalidate`, so a push needs no invalidation: the page revalidates and names the new hashes. `kit.hash` in `site.json` is the switch and `HASHED` in `scripts/push.ts` is the rule. - `bun run push` ships `dist/` to the site bucket by manifest diff; `--dry` lists every hashed path it would upload, counts the rest, and writes nothing. Deletes come from that same diff, the paths the remote manifest carried and this build no longer writes; only when the remote manifest is missing does it sweep one flat listing of the bucket instead. Either way every `cdn/` key is dropped, so it never uploads to or deletes under that prefix: that space is the game reels', not the site's. - `/git/` is the code viewer from `kit/git`: it browses this repo's own tracked tree, `/raw/` serves the bytes, and the `git` block in `site.json` names the root, the GitHub slug and the branch. - The sidebar is `sidebar()` in `lib/tree.js`: under each door one flat alphabetical list of every demo, paper, note and post, each named by its url slug capitalised (`/demos/morse/` reads `Morse`), and only the door holding the current page opens; titles, blurbs and the demo shelves belong to the galleries and `/menu/`, which read `tree()`. - The tree carries one collapsed `Code` node; the pages under it stay out of the navigator, and every one of them plus every `/raw/` object enters the sitemap. - `site.json` carries the `llms` block: the paragraph `llms.txt` opens on and the links it points at, `/raw/README.md`, `/research/`, `/git/` and `/papers/`. - `robots.txt` allows everything and names GPTBot, ClaudeBot, Claude-Web, CCBot, Google-Extended, anthropic-ai and PerplexityBot one block each. - The highlighter is the kit's, server-side Shiki over 16 grammars; `ui/code.css` rides with `seti.css` on every code page. - `public/pages.css` carries only what the kit has no rule for: the tiles, the home, the openers, the plates and the `Elsewhere` list; the code viewer's own CSS lives in the kit's `code.css`. - Every route carries a canonical link, a description, Open Graph and Twitter cards pointing at the one `/og.png`, and JSON-LD where it has an author. - A note, a page, a post or a paper names a single figure by writing its bare name as an image target, `![caption](walks-fig)`: the build finds `../files/figures/walks-fig.png`, ships it as `/figures/walks-fig.png` with the route, and throws when the file is missing. - `bun run check` prints the fixture numbers the crate's host test asserts; both must agree. - `site.json` declares every input the build reads: `readme pages blog wiki research figures demos lib pkg ui public`; nothing is resolved by hand, so a path moves in one place. - Every markdown link, on a research note, a page, a post, a paper or a `/git/` page, goes through the kit's one resolver in `kit/ssg/links.ts`: it resolves the link against the file it was written in, answers with the route this site publishes for that file when there is one, falls to `/git/` or `/raw/` when the repo carries it, and leaves it alone otherwise. - `pkg/`, `dist/`, `data/`, `.cache/` and `node_modules/` are build output and stay out of git.