wesandClaude Opus 5 d3d93a982a reading map: seven models, one library — /reading/models
The same 9,194 passages arranged by seven embedding models, switchable. Every
model's coordinates are Procrustes-aligned to nomic, without which the toggle
would be seven unrelated arrangements and the motion between them meaningless.

⚠️ The page states the NEIGHBOUR-AGREEMENT number, not the animation, and the
distinction is load-bearing. Every projection of 1024 dimensions into 3 is lossy
in a way that shapes what you see: measured directly, PCA and UMAP disagreed by
10x about whether whole books move together, each reporting its own arithmetic.
So the claim is computed on the raw embeddings where there is no projection to
be an artifact of (models share ~50% of each passage's 15 nearest neighbours),
and the picture illustrates that number rather than being the evidence for it.
The page says so in as many words.

Renderer gains setCoordinates(), driven from the existing render loop rather
than its own rAF so a morph cannot outlive the scene or run while scrolled away.
It writes through the single `xyz` buffer the nebula, signal and trace all read
from, so every layer moves together and nothing drifts out of registration.

`trace` is now optional. The banner and explorer always carry one; a comparison
payload legitimately does not — its subject is where passages MOVE between
models, not the order they were highlighted in.

Payload is split: a 44 KB manifest with everything shared, plus one ~145 KB
coordinate file per model fetched on demand. The per-node book/kind arrays are
identical across models, so carrying them seven times is waste, and eager
loading would be ~1.1 MB before first paint.

auto-build.sh now watches public/reading_*.json as ONE glob. The previous
OR-chain was subtly broken — with `-o` the `-printf` binds only to the last
clause, so earlier matches printed in a different format and the signature was
not stable. The glob also picks up future payloads without an edit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 13:40:11 -04:00

garden-astro

Astro rebuild of the digital garden at garden.c0smere.net, replacing Quartz v4. Content stays in the Obsidian vault (Digital_Garden/ folder); this repo is only the rendering pipeline.

URL compatibility

Built to be a drop-in replacement — every URL on the live Quartz site resolves identically here (verified against the live sitemap, 102/102):

  • case preserved, spaces become -, hyphens/em-dashes kept
  • leaf pages: /Folder/Note-Name (build.format: 'file' + nginx try_files $uri $uri.html)
  • folder indexes: /Folder/ (from Folder/index.md, or a synthetic listing page when no index exists)

Obsidian compatibility (src/lib/remark-obsidian.mjs)

  • [[wikilinks]] with aliases/anchors, resolved vault-path-first then by basename; unresolved links degrade to plain text
  • ![[image embeds]] and relative ![md](images) both rewrite to flat /assets/<name> URLs; scripts/copy-assets.mjs resolves the files (Digital_Garden first, then vault-wide) and copies them in at build time
  • > [!type] callouts, KaTeX math, mermaid (lazy-loaded client-side only on pages that use it), shiki dual light/dark themes
  • draft: frontmatter excluded, including Quartz-style quoted "true"

Build

GARDEN_CONTENT=/path/to/vault/Digital_Garden npm run build

Defaults to the kotov vault copy. On cyrion use deploy/build.sh (containerized node:24, vault mounted read-only), then docker compose -f deploy/docker-compose.yml up -d serves dist/ on port 18100, proxied as garden.c0smere.net (NPM public + Caddy internal).

marimo notebooks (/notebooks)

Notebooks from the marimo server (/home/nox/docker/marimo/notebooks/) can be published into the garden. A notebook publishes only if it opts in, by carrying this HTML comment in one of its markdown cells — invisible in the rendered page, greppable in the .py source:

<!-- garden:publish
title: Dream of Spotification
description: A decade of Spotify history, worked two ways.
order: 30
-->

Only the garden:publish line is required. Optional keys: title, description, order (sort weight, default 100), slug (URL override, default derived from the filename), timeout (export seconds, default 600). Delete the marker to unpublish — the next export run removes the page.

This is deliberately default-deny: garden.c0smere.net is public and the export bakes each notebook's executed output into the page, not just its code. deploy/export-notebooks.py also carries a NEVER_PUBLISH list (genome_*, coursework) as a second latch, so a marker pasted into one of those refuses loudly instead of publishing.

Pipeline:

  1. deploy/export-notebooks.py (own timer, garden-notebooks-export.timer, every 30 min; own lock) scans for markers and runs each opted-in notebook in a one-shot marimo:latest container — same image and .env as the live server, so it hits the real databases. Output lands in notebooks-export/<slug>.html plus an index.json.
    • Cached on notebook content: a run after no edits does no work.
    • Per-notebook timeout, and a failure keeps the previous export and continues. A broken notebook can't take the garden down.
    • It runs against a throwaway copy of the notebook dir, so notebooks that write scratch files don't dirty the notebooks git repo.
  2. scripts/copy-notebooks.mjs stages those into public/nb/<slug>.html.
  3. Astro reads index.json (src/lib/notebooks.mjs) to build /notebooks and /notebooks/<slug>, which wrap the raw export in an iframe with the garden chrome, plus the sidebar section.

The raw export is at /nb/<slug>.html, deliberately not under /notebooks — with build.format: 'file' the page and the raw file would collide on the same URL.

URL shapes here are worth knowing, since build.format: 'file' makes the listing a file (dist/notebooks.html) that sits beside a directory of detail pages (dist/notebooks/<slug>.html). Verified against the running nginx: /notebooks and /notebooks/<slug> resolve through the generic try_files, but /notebooks/ does not — a bare directory has no index.html. deploy/nginx.conf carries an explicit location = /notebooks/ so the trailing-slash form works like every other folder URL on the site.

Both notebooks-export/ and public/nb/ are gitignored: tracking them would make every export dirty the tree, which flips auto-build.sh's change signature and breaks the git pull at the top of each build tick. The signature hashes notebooks-export/ separately instead.

Force a full re-export with deploy/export-notebooks.py --force.

Layout extras

Every page carries a left sidebar tree of the whole garden (folders collapsible, current page highlighted; flows after the footer on narrow screens) and the bandwidth odometer in the footer, fed by https://api.c0smere.net/bandwidth/odometer. The widget animates at the lifetime average rate from a fetched baseline — it never reflects live throughput, and hides itself if the API is down.

S
Description
Astro rebuild of the digital garden (Quartz replacement) with Quartz-compatible URLs
Readme
851 KiB
Languages
Astro 52.9%
JavaScript 26.7%
Python 9.6%
CSS 6.5%
TypeScript 2.5%
Other 1.8%