./jerome{m}

~/Notes/How this site works.md · note · evergreen · 4 min · updated

How this site works

// status: evergreen

This site is still an Obsidian vault: ordinary Markdown with wiki links and frontmatter, written in Obsidian or in nvim. What changed is everything after the save. A small Rust static site generator called jm turns the vault into plain HTML, and the parts that should move are islands: little programs drawn by gpui, the GPU UI framework behind the Zed editor, compiled to WebAssembly.

The shape of the system

Markdown notesvault: parse, links,embedsjm: pages, search, artstatic HTMLgpui islandswasmRaym: C + raylibEmscriptenCloudflare PagesMarkdown notesvault: parse,links, embedsjm: pages, search,artstatic HTMLgpui islandswasmRaym: C + raylibEmscriptenCloudflare Pages
diagramhover a box to trace it · click to zoomtap to zoom and pan

Everything lives in the same repository as the notes. The vault crate reads them, resolves links and embeds; jm renders pages, the search index, the link graph and the generated art; jm publish checks the vault and deploys the whole folder.

Text first, programs where they earn it

Every page is real HTML. Search engines, link previews, reader mode, translation, screen readers and plain old find-in-page all work, and the URLs are the same ones the site has always had.

The interesting parts are islands. A fenced block in a note is all it takes:

markdown
```embed life
seed: 1337
caption: The same rules, live.
```
life · liveAn island: a gpui app compiled to wasm, running inside this note. Click to pause, right-click to reseed.open ↗

gpui wants a whole page to itself, so each island is its own tiny page in a lazy <iframe>. It only loads when it scrolls into view, never takes keyboard focus while it boots, and ignores the mouse wheel until you click it, so reading is never hijacked. In Obsidian the same block is just a code block.

There are a few of them so far. Conway's Game of Life runs live. The Monkey interpreter I wrote in 2017 runs as a REPL, seeded with the code from its own write-up. Raym is not gpui at all: it is the original C and Raylib code compiled with Emscripten to WebGL 2, with only the main loop and the shader headers adapted for the browser. The link map in the sidebar is another gpui island, a small force simulation over every wiki link in the vault.

A dithered distance field

The background is an SDF-inspired contour field, quantised through an 8×8 Bayer matrix into four levels of one warm tint. It now runs at one canvas pixel per four-pixel cell, which makes it cheap enough to move: the rings drift outwards very slowly, the cursor leaves ripples, and every page seeds its own origin. It stays behind the text, and reduced-motion gets a still image.

Art made at build time

Some of the look is generated when the site is built rather than in the browser:

  • every note gets a ridgeline signal above its title, its peaks seeded by the note's own path;
  • every screenshot gets a 1-bit, ordered-dither twin in accent yellow, and the original fades in when you hover it;
  • every note gets its own social card, with the same contours, a dithered cover and the title set in the site's fonts;
  • code is highlighted ahead of time, so a page never waits on a highlighter.

Page transitions borrow the same idea: in browsers that support cross-document view transitions, the next page develops through an ordered dither.

Design decisions

  • Yellow is an accent; long-form text uses a high-contrast neutral colour.
  • Atmosphere sits behind the content, never on top of it.
  • Islands are opt-in per note and cost nothing until you reach them.
  • Keyboard focus stays visible, and motion respects reduced-motion settings.
  • Project pages pair atmosphere with evidence: source links, screenshots, live islands, and related notes.

Publishing without surprises

Public pages opt in with publish: true, and only Notes/, Experiments/ and a handful of root pages are ever read: Inbox/, Sources/ and scratch/ cannot leak, because the generator never opens them. jm check refuses broken wiki links and missing attachments, and jm publish runs it before building anything. The whole site is a folder of static files on Cloudflare Pages; no subscription, no remote selection to review, no forgotten page to unpublish by hand.

Why build it this way?

Because the site is also a workshop. I can link a rendering note to an experiment while the idea is fresh, and now the experiment itself can live inside the note. Markdown keeps the writing mine and portable; the generator and the islands are just more Rust and C to tinker with.


Back to Home · browse the Notes · explore the Experiments.