README.md
12.4 kB · markdown
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 installfetches them;bun run wasmbuildspkg/fromcrates/mrlydemowith wasm-pack.- One demo is one folder: a thin
demos/<name>/index.htmlshell plusdemos/<name>/index.jsx; the gallery isdemos/index.html+demos/index.jsx. - A demo registers nowhere: the folder is the list, its
<title>is the title, itsdescriptionmeta is the blurb, and itsshelfandordermetas 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">, andPageinapp.jsxprints it as one Read line under the foot. - The eight shelves are the
shelvesblock insite.json,key,group,titleandblurbeach; the build groups the demos by them intodemos/tree.jsonand injects that same JSON into every demo head as<script type="application/json" id="mrly-tree">, whichtree.jsreads 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.jsxis the sequence-view kit,Pins,Staircase,Digits,Ratios,Differencesand theTermsribbon, 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.pnganddemo-<name>-light.png, and the demos route ships them. - The chrome is the kit in
kit/uiand its README is the reference for it: the header glyphs, the three columns, the drawers, the menu and the settings read fromsite.json, and the footer is one screen, the wordmark held by the pixel-font animation over a copyright line, with no links;app.jsxwraps itsShellasPagebesidemount,Rowand the controls,tree.jsfills the site tree from the injected demo shelves plus the papers, research and blog lists, andmrly.cssimports the kit and keeps only demo rules;draw.jsxwraps every canvas:Grid,Signs,Pixels,Sketch,Markup. Signsis the plus-minus primitive: a warm hue for plus one, a cool hue for minus one, and the dark ground for empty.select.jsxis the one picker: design list, code, base and Randomize;?seed=7replays the seventh tap, and a typed code drops the seed.useQueryinquery.jskeeps page state in the URL, so every view is a link.- Words live as markdown:
blog/<slug>.md,../research/papers/<slug>.mdand everypages/<slug>.mdopen with a---front matter block (title, date, lead, optional figure naming a file infiles/figures/); one page file is one route,/<slug>/;public/copies straight to the site root. - The widget line: a wiki page writes
on a line of its own and the build mounts that view in place;demos/<name>/widget.jsxexports the view as a component named<view>and callsembed('<name>', { <view> })fromlib/widget.jsx, which mounts everyfigure.widget[data-demo]on the page; the page loads/demos/<name>/widget.js, an entry of the demos' oneBun.buildcall, 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>.mdis the wiki input: front mattertitle,lead,prerequisites(wiki slugs, comma-separated) and an optionalfigure(defaultwiki-<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 devrenders on request: it scans once, watches every declared input and template, and renders the route you ask for; nothing is prebuilt anddist/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 buildwrites the whole site todist/withscripts/site.tsalone: pure bun, no Chrome, no cargo, no Python;bun run cleanemptiesdist/by hand when you want a cold start.MRLY_DIST=/some/dirwrites there instead, manifest included, so two builds never share a folder.- The demos are one route: one in-process
Bun.build()overdemos/index.htmlanddemos/*/index.html, its SEO head injected before the shells are written, fingerprinted overdemos/,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: trueand the hashedchunknaming inscripts/site.ts; without them every demo ships its own React. - A second
bun run buildrenders nothing: every route is fingerprinted into.cache/manifest.jsonwith 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/frombun run wasmand../files/figures/frombun run figures(thefigurescrate on themrlyfigkit); every figure is a pair,<name>-dark.pngand<name>-light.png, the page carries both asimg.darkandimg.lightand 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>andsite-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.tsfetches the paper shelf from GitHub intodata/shelf/at every build and falls back to the cached copy offline;SHELF_REPO=owner/reponames the shelf and unset means no fetch,MRLY_SHELF=/path/to/researchreads a local checkout instead, whichbun run devandbun check.tsboth 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, besidesitemap.xml,robots.txt,llms.txt,manifest.webmanifestand 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 ofresearch/claims/, the three latest papers and the latest post. /tools/is thethinkind, one landing with its figure and a line on what is coming, held for the tools plan to fill;/math/is themathkind and renderscrates/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 pagesite-code, and only/menu/,/cart/,/blog/,/404.htmland a markdown page without a figure fall back toog.png. /menu/lays the whole navigator out with the kit'sMenuas a figure grid, one picture tile per route with its blurb, closing on anElsewherelist 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 shotsservesdist/itself, drives one headless Chrome on one port with one throwaway profile, and writes ten full-page pngs, five routes at phone and desktop, intodata/mrlyprod/site/scripts/shots/latest/, killing Chrome at the end; routes as arguments replace the five,--printemulates print media,--js <expr>prints an expression per shot,--baselinekeeps 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/andseti/keep their names because their CSS names the faces by relative url, and every HTML page, figure and text file goes out atmax-age=0, must-revalidate, so a push needs no invalidation: the page revalidates and names the new hashes.kit.hashinsite.jsonis the switch andHASHEDinscripts/push.tsis the rule. bun run pushshipsdist/to the site bucket by manifest diff;--drylists 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 everycdn/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 fromkit/git: it browses this repo's own tracked tree,/raw/serves the bytes, and thegitblock insite.jsonnames the root, the GitHub slug and the branch.- The sidebar is
sidebar()inlib/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/readsMorse), and only the door holding the current page opens; titles, blurbs and the demo shelves belong to the galleries and/menu/, which readtree(). - The tree carries one collapsed
Codenode; the pages under it stay out of the navigator, and every one of them plus every/raw/object enters the sitemap. site.jsoncarries thellmsblock: the paragraphllms.txtopens on and the links it points at,/raw/README.md,/research/,/git/and/papers/.robots.txtallows 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.cssrides withseti.csson every code page. public/pages.csscarries only what the kit has no rule for: the tiles, the home, the openers, the plates and theElsewherelist; the code viewer's own CSS lives in the kit'scode.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,
: the build finds../files/figures/walks-fig.png, ships it as/figures/walks-fig.pngwith the route, and throws when the file is missing. bun run checkprints the fixture numbers the crate's host test asserts; both must agree.site.jsondeclares 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 inkit/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/andnode_modules/are build output and stay out of git.