Commit Graph
7 Commits
Author SHA1 Message Date
wes bd6910a5dd Reading map: ring the newest highlight and the one quoted in the header
Two standing markers, drawn as rings rather than brighter dots. The animated
trace head is already a bright point and comes to rest on exactly the newest
node at the end of every draw cycle — under prefers-reduced-motion it parks
there permanently — so a second filled dot at that coordinate would read as a
rendering fault. Outlines say "different kind of thing" without competing.

The newest highlight is the LAST trace entry, never the max of `t`: the
payload is pre-sorted, `t` is date-only, and many highlights share a day.

The quoted one is looked up by text_hash, which /highlights/random now
returns beside the quote. The two fetches race on every page view, so the
hash is published both as a global and as a `garden:quote` event — one covers
each order. About one highlight in fifteen has no node, because its source
book was never indexed; markQuoted returns false and nothing is drawn.

Rings are flat geometry parented to the rotating world, so they are
billboarded each frame or they would vanish edge-on twice a revolution.

Also adds the "Currently reading" rail widget. It says how long ago on
purpose: six of the ten books on that shelf have not been opened in months,
and without a relative date the thing looks broken rather than honest. Past
45 days it mutes itself. No cover — kobo.books.isbn is a sideloader's UUID
for most of the shelf and storygraph_links has no cover URL.

The TOC rail is now always rendered, since it carries the widget too; it was
conditional on having two headings, which would have hidden the widget on the
homepage. Hidden explicitly on wide notebook pages, where a third grid child
would wrap under the sidebar.
2026-08-14 08:45:12 -04:00
wesandClaude Opus 5 4dbf8fe526 Reading map: honour reduced-motion for the orbit; give /knoebels a real nav link
Two follow-ups on yesterday's hero.

The `prefers-reduced-motion` branch only skipped the trace *animation* — the
scene kept orbiting continuously, which is precisely what a reader who asked for
reduced motion is asking not to get, on the homepage no less. The cloud now
holds still; it still renders in full.

/knoebels was reachable only from the homepage crowd strip, and that strip is
hidden whenever the park API is unreachable — so an API outage made the page
unreachable from anywhere on the site. It gets a sidebar entry, the same way
/notebooks does, since neither is a vault note that buildNavTree could carry.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 08:51:36 -04:00
wesandClaude Opus 5 9519c46fe2 Reading map: a 3D hero of everything read, traced by what I highlighted
An orbiting point cloud of all 8,424 indexed passages, with the 262 highlighted
ones lit and threaded in the order they were marked. Data comes from library-rag
(chunks + embeddings) projected to 3D with UMAP; the page never touches Postgres.

Projection is `airy` (n_neighbors=50, min_dist=0.8) and the palette is `frost` --
both chosen by eye against the alternatives. Note that airy shows the underlying
book-territory structure LESS than the tight projection the pre-flight measured,
so the 0.805 k-NN purity figure describes that one, not this.

Page weight: the wrapper adds 321 B gzip to the homepage's blocking load. `three`
(127 KB gz) and the payload (56 KB gz) are a dynamic chunk fetched after render.
It fails closed -- no WebGL, no payload, or a dead fetch leaves a plain page.

The payload is a static snapshot; the 5-minute auto-build rebuilds the site, not
the data. New reading reaches this map only when export.py is re-run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 08:30:45 -04:00
wesandClaude Opus 5 9da9a6cba2 Publish opted-in marimo notebooks at /notebooks
Notebooks from the marimo server can now appear in the garden. A notebook
opts in with an HTML comment in one of its markdown cells — invisible when
rendered, greppable in the .py source:

    <!-- garden:publish
    title: Dream of Spotification
    order: 30
    -->

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

Pipeline: export-notebooks.py runs each marked notebook in a one-shot
marimo container (same image/env/GPU as the live server, so it hits the real
databases) into notebooks-export/ + index.json; copy-notebooks.mjs stages
those to public/nb/; Astro reads index.json to build the pages and the
sidebar section.

Isolation choices worth keeping:

- Own timer and own lock, separate from the 5-min garden build — executing a
  notebook takes minutes and must never hold up a build tick.
- Cached on notebook content; both index.json and .cache.json go through
  write_if_changed, since auto-build.sh hashes mtimes under notebooks-export/
  and an unconditional rewrite would force a full rebuild every 30 minutes.
- Per-notebook timeout; a failure keeps the previous export and continues.
- Runs against a throwaway copy of the notebook dir, so notebooks that write
  scratch files don't dirty the notebooks repo.
- Notebooks are NOT injected into the garden collection — they aren't vault
  notes, and doing so would move noteCount and the sitemap.

build.format:'file' makes the listing a file (notebooks.html) beside a
directory of detail pages. Verified against the running nginx: /notebooks and
/notebooks/<slug> resolve through the generic try_files but /notebooks/ does
not, so nginx.conf gets an explicit location for the trailing-slash form.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 22:07:14 -04:00
wesandClaude Fable 5 8f48656e91 Build stamp, live listening strip, OG cards, closer shiki ground
- footer: 'built <ts> · <hash> · <n> notes', hash linking to Gitea
  (GARDEN_COMMIT passed in by build.sh; '+' marks dirty-tree builds)
- homepage header: live strip fed by api.c0smere.net/spotify/summary
  (weekly aggregate + monthly top artist/genre), fail-closed like the
  odometer and header quote
- /og/<slug>.png satori+resvg cards for every note + the homepage;
  og:/twitter: meta in Base
- shiki github-dark-default (#0d1117 sits closer to the page ground)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 22:08:53 -04:00
wesandClaude Opus 4.8 13b23ace3d Sidebar nav: full garden tree on every page
- buildNavTree: every non-draft page nested by vault folder; folders link
  to their (real or synthetic) index page and take its title when set
- NavTree component: recursive details/summary tree, no JS — folders on
  the current path render open, current page gets aria-current styling
- layout: sticky left sidebar >=72rem, flows after the footer as a site
  index on narrow screens

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 14:54:04 -04:00
wesandClaude Opus 4.8 04c9aa2fb2 Astro garden skeleton: Quartz-compatible URLs, Obsidian markdown, odometer homepage
- glob content loader over the vault's Digital_Garden with verbatim-path ids
- remark plugin: wikilinks, image embeds (wiki + relative md), callouts
- URL parity with live Quartz sitemap verified 102/102 (built set is a
  strict superset: +30 synthetic folder listings)
- KaTeX, lazy mermaid, shiki dual themes, quoted-string draft handling
- copy-assets resolves embeds vault-wide (fixes live-site 404s for
  Blog Scratch/assets images) into flat /assets/
- homepage odometer widget: fetches api.c0smere.net baseline, ticks at
  lifetime average rate, fail-closed hidden on error
- deploy/: nginx try_files config + compose (port 18100) + containerized
  build script for cyrion

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 14:18:59 -04:00