site

8 directories and 7 files in site.

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/<name>/index.html shell plus demos/<name>/index.jsx; the gallery is demos/index.html + demos/index.jsx.
  • A demo registers nowhere: the folder is the list, its <title> 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.