Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
4b62e56
taskbar: Quick Launch profile icons + first-level subpages as app but…
oddharsh Jun 7, 2026
54f6f73
desktop shortcuts, Run hot-tracking, Temporal clocks, Luna base-select
oddharsh Jun 7, 2026
71832e6
windows: true OS-window scroll model (frame pinned, content scrolls i…
oddharsh Jun 7, 2026
74d7504
windows: custom scrollbar, drag boundary, draggable icons, resize
oddharsh Jun 7, 2026
d0a4769
writing: open notes as popovers that composite over the folder
oddharsh Jun 7, 2026
0e8f1e0
windows: icons under windows, fixed-size thumbnails, no-tooltip-on-sc…
oddharsh Jun 7, 2026
64123f8
section favicons + repo cleanup (clean engine bay)
oddharsh Jun 7, 2026
58bbee7
desktop icons: relabel Instagram->Photos, Spotify->Music
oddharsh Jun 7, 2026
d131f60
writing: let multiple notepads stay open at once
oddharsh Jun 7, 2026
703a99b
fix writing resize, serendipity sidebar gap; snappier tooltips
oddharsh Jun 7, 2026
73e7ebf
dates: use Temporal (with Date fallback) for image + serendipity dates
oddharsh Jun 7, 2026
13b0807
footer: auto-derive "Last modified" from the newest photo (no more st…
oddharsh Jun 7, 2026
30dcf20
frontier: shell-wide Speculation Rules + container queries + site-wid…
oddharsh Jun 7, 2026
1e758ea
vt: kill the white flash by painting the ROOT (html) with the Bliss tone
oddharsh Jun 7, 2026
a480e9b
vt: make the window morph snappier
oddharsh Jun 7, 2026
646fecf
vt: map the window transition to XP's minimize/restore zoom
oddharsh Jun 7, 2026
0758db2
chore: gitignore .claude/ local tooling (launch.json, worktrees)
oddharsh Jun 7, 2026
74878ca
scrollbar: inset off the window frame + leave the corner for the resi…
oddharsh Jun 8, 2026
1096053
garage: add "Safari 27, through this site's lens"
oddharsh Jun 9, 2026
5ce0c98
garage/safari27: fold in the WWDC26 web-technology sessions roundup
oddharsh Jun 9, 2026
456f245
garage: prototype a masonry photo grid (CSS Grid Lanes)
oddharsh Jun 9, 2026
61a8de8
garage: narrow-window hardening + LRS voice pass (safari27, masonry)
oddharsh Jun 9, 2026
a71e4c4
writing: add "Education in tech" note
oddharsh Jun 9, 2026
51c9483
perf + Luna fidelity pass (luna-perf)
oddharsh Jun 9, 2026
ac4a2be
luna polish: 8/8 corners, honest amber tokens, Run-dialog + Geneva sweep
oddharsh Jun 9, 2026
b082ba5
garage: LRS voice pass across index + 7 demo pages
oddharsh Jun 9, 2026
fd9f338
garage: LRS craft pass (character-action cores, kill nominalizations)
oddharsh Jun 9, 2026
874f113
titles: filepath separator sitewide (aadhar.sh / section / page)
oddharsh Jun 9, 2026
0dc0fa0
titles: tighten separator to slash-tight (aadhar.sh/garage, no spaces)
oddharsh Jun 9, 2026
4412417
writing: show per-file character count in the folder index
oddharsh Jun 9, 2026
ce566da
serendipity: ship the read-only MCP server at /serendipity/mcp
oddharsh Jun 9, 2026
cf2bdcc
serendipity: add contributor + person-history MCP tools; agent discov…
oddharsh Jun 10, 2026
5e6f82f
perf+correctness: audit fixes (cache poisoning, fallbacks, TTFB, SWR)
oddharsh Jun 11, 2026
f542eab
perf: cache nav.js + notepad.js (5min + SWR) so SW-less navs skip the…
oddharsh Jun 11, 2026
13a1479
perf: inline OS-window geometry so first paint matches nav.js (no she…
oddharsh Jun 11, 2026
f42f819
consistency + docs sweep + Run-palette selection (audit low-sev batch)
oddharsh Jun 11, 2026
26f7d26
garage: add the "Teardown" page documenting Fable 5's audit (before/a…
oddharsh Jun 11, 2026
cc8008f
perf: extend the inline first-paint geometry to the worker-rendered p…
oddharsh Jun 11, 2026
bbe7b53
garage: add "iroh" — evaluate the P2P library + a native NodeId demo
oddharsh Jun 15, 2026
6ba3f31
docs: add MAINTENANCE.md ops runbook
oddharsh Jun 15, 2026
43a4b5e
homepage: label the now-playing heading as "the playlist" so it reads…
oddharsh Jun 15, 2026
31379f7
serendipity MCP: add the social-graph tools (frequency + co-attendance)
oddharsh Jun 15, 2026
728db29
homepage: instant thumbnail tooltips on desktop + fix the panel/scrol…
oddharsh Jun 15, 2026
0d75ed8
homepage: tooltips return instantly when scrolling settles
oddharsh Jun 15, 2026
8226e6a
homepage: kill the grid-reflow CLS when the deferred shell mounts
oddharsh Jun 15, 2026
916dbe0
site-wide: reserve the scrollbar gutter at first paint on every windo…
oddharsh Jun 15, 2026
578a07a
homepage: fix the visitor counter falling back to "000042" (DO-only, …
oddharsh Jun 16, 2026
e0cacf8
homepage: add a BIMI logo — an original paperclip-assistant mascot
oddharsh Jun 16, 2026
78672ab
homepage: swap BIMI logo to the traffic cone + drop the kitschy "EXIF…
oddharsh Jun 16, 2026
084b6b3
garage/cloudflare: add a custom-spans tracing demo (cf-garage feature…
oddharsh Jun 16, 2026
bc2bccb
site-wide: make the scrollbar gutter authoritative (fix panels kissin…
oddharsh Jun 16, 2026
85d2d29
serendipity/mcp: tier events by RSVP — hide browsed-but-not-attended …
oddharsh Jun 17, 2026
f36b6d9
serendipity: demote browsed events in the dashboard + add Parallel as…
oddharsh Jun 18, 2026
95e369e
garage/horizon: refresh stale cross-engine statuses (June 2026)
oddharsh Jun 18, 2026
59332df
garage/horizon: add the bleeding-edge + networking batch (10 new cards)
oddharsh Jun 18, 2026
a17f28a
site-wide: adopt cross-document View Transitions + Service Worker sta…
oddharsh Jun 18, 2026
5300a0d
garage/horizon: mark shipped-to-production cards (translucent green) …
oddharsh Jun 18, 2026
b489539
nav.js: add Raycast deep-link easter eggs to the Run palette (confett…
oddharsh Jun 18, 2026
37bd5b5
content-visibility on the long pages + Compression Dictionary Transpo…
oddharsh Jun 18, 2026
6d64aa0
nav.js: remember the window-content scroll across quick reloads
oddharsh Jun 18, 2026
e9a442a
cal: add vitest harness (workers runtime) + fix two .ics unicode bugs…
oddharsh Jun 18, 2026
ce33c09
cal: make wrangler.toml deploy-ready (fix custom-domain route + wire …
oddharsh Jun 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ npm-debug.log

# cf-garage worker deps (not committed)
cf-garage/node_modules/
.claude/launch.json
.claude/worktrees/
360 changes: 360 additions & 0 deletions AGENTS.md

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ colors that read modern in source but render period-correct.

## Quick reference

> Full task-by-task ops runbook (add photos, swap the now-playing playlist,
> bust caches, version bumps, what every script does): [MAINTENANCE.md](MAINTENANCE.md).

```bash
# deploy the homepage
wrangler pages deploy holding --project-name aadhar-sh --branch holding --commit-dirty=true

# add new photos (resize, EXIF-rotate, encode to JPG+WebP, upload to R2,
# add new photos (resize, EXIF-rotate, encode to AVIF+JPG, upload to R2,
# regenerate metadata.json, bust manifest cache)
./holding/scripts/add-photos.sh "/path/to/photo.HIF" /path/to/folder/

Expand Down Expand Up @@ -47,19 +50,19 @@ Single-page personal site at `aadhar.sh`. Hosted on Cloudflare Pages, with a

| file | role |
|---|---|
| `holding/index.html` | The whole page in one file. Inline CSS + JS. ~65KB uncompressed, ~19KB brotli. Comments deliberately kept for the `/source` view. |
| `holding/index.html` | The whole page in one file. Inline CSS + JS. ~78KB uncompressed, ~22KB brotli. Comments deliberately kept readable for View Source. |
| `holding/writing/` | Written content as plain `.txt` files + `posts.json` registry `[{slug,title,date}]`. The worker renders each as an XP **Notepad** window at `/writing/<slug>` (a server-rendered `<textarea>` seeded with the canonical text — editable by nature, ephemeral by nature: no save → reload restores canonical, "writing in flux"), plus a "My Writing" folder index at `/writing`. Raw `.txt` stays fetchable at `/writing/<slug>.txt`. Author a post = drop a `.txt` + a `posts.json` entry. Render code (`handleWritingIndex`/`handleWritingPost`/`NOTEPAD_CSS`) lives in `_worker.js`. |
| `holding/notepad.js` | Behavior for the `/writing` Notepad view (deferred, SW-cached): working File/Edit/Format/View/Help menus, live Ln/Col + word-count status bar, Word-Wrap toggle, the classic **F5 time/date** stamp, Select All, Print, About. Chrome itself is SSR'd by `_worker.js`; this only wires interactions. No-op without a `.np-window`. |
| `holding/nav.js` | Site-wide XP **taskbar + Run command palette**. The ONE shared external asset (deferred, SW-cached) — every page includes `<script src="/nav.js" defer>`; it injects its own `<style>` + builds the taskbar (Start orb → Run, pinned footer profiles, clock) and the Run dialog into `<body>`. Opens via ⌘K / Start / taskbar. Destinations: pages + profiles inline; 131 photos lazy-loaded from `/images/manifest.json` with `/images/alt.json` captions as search labels. Wired into homepage + all garage pages + worker-gen `/around`,`/whoareyou`,`/bot` + serendipity shell. |
| `holding/_worker.js` | Pages-Worker hybrid. Owns routing, photo serving from R2, manifest building, Spotify playlist scraping, AadharshBot crawler, /source viewer, /coffee redirect, cache-control overrides. |
| `holding/notepad.js` | Behavior for the `/writing` Notepad view (deferred, SW-cached): per-window `enhance()` wiring File/Edit/Format/View/Help menus, live Ln/Col + word-count status bar, Word-Wrap toggle, the classic **F5 time/date** stamp (Temporal w/ Date fallback), Select All, Print, About. Also opens folder notes as **popovers** that composite over the folder index (+ `pushState` to `/writing/<slug>`, Back closes). Chrome itself is SSR'd by `_worker.js`. No-op without a `.np-window`. |
| `holding/nav.js` | Site-wide XP **desktop shell**. The ONE shared external asset (deferred, SW-cached) — every page includes `<script src="/nav.js" defer>`; it injects its own `<style>` + builds, into `<body>`: the **Bliss desktop** wallpaper, **draggable desktop icons** (Notepad + the 5 profiles, positions persisted in localStorage), the **taskbar** (Start orb → Run, first-level-subpage app buttons each with a per-section SVG icon, clock via Temporal), and the **Run** command palette (⌘K / Start). Also owns the **OS-window model**: body is a clipping flex desktop, each `.window`/`.np-window` is pinned + its content scrolls internally behind a **custom XP scrollbar**, windows are **draggable** (top is a hard boundary) + **resizable**, and View Transitions animate only the window. Sets each first-level route's **tab favicon** to its section icon. Run destinations: pages + profiles inline; 146 photos lazy-loaded from `/images/manifest.json` with `/images/alt.json` captions. Wired into homepage + all garage pages + worker-gen `/around`,`/whoareyou`,`/bot` + serendipity shell. |
| `holding/_worker.js` | Pages-Worker hybrid. Owns routing, photo serving from R2, manifest building, Spotify playlist scraping, AadharshBot crawler, the `/writing` Notepad pages, cache-control overrides. |
| `holding/_headers` | Static-asset cache + security headers (CSP, Permissions-Policy, etc.). Applied to direct static-asset requests; the worker overrides cache-control for select paths. |
| `holding/sw.js` | Service worker. `CACHE_VERSION = "aadhar-v5-webp-jpg"`. Cache-first for `/images/*` (content-addressed via `?v=N`), SWR for static text files, network-only for everything else. Bumping `CACHE_VERSION` sweeps old caches. |
| `holding/sw.js` | Service worker. `CACHE_VERSION` (see holding/sw.js line ~28 for the current version) bumps on every nav.js/notepad.js change. Cache-first for `/images/*` thumbnails only (content-addressed via `?v=N`; full-res `/images/full/*` deliberately excluded — browser HTTP cache holds those immutable), SWR for static text files + nav.js/notepad.js, network-only for everything else. Bumping `CACHE_VERSION` sweeps old caches. |
| `holding/llms.txt` | The llms.txt format — concise site summary for LLMs. Linked from `<link rel="alternate">`. |
| `holding/index.md` | Markdown source of homepage copy (used by `/llms.txt` and as a fallback). |
| `holding/sitemap.xml`, `robots.txt` | Standard SEO files. robots.txt explicitly allows AadharshBot. |
| `holding/.well-known/http-message-signatures-directory` | JWKS for AadharshBot's Ed25519 public key (Web Bot Auth IETF draft). |
| `holding/images/` | 120 thumbnails (1200px AVIF + JPG pairs) + `metadata.json` (EXIF index). 120 stems × 2 formats = 240 files. |
| `holding/scripts/` | Photo-pipeline scripts (see below). |
| `holding/images/` | 146 thumbnails (1200px AVIF + JPG pairs + 400px mobile AVIF tier) + `metadata.json` (EXIF index) + `meta/<stem>.json` per-photo EXIF for the hover tooltip. |
| `holding/scripts/` | Photo-pipeline + asset scripts (see below). Beyond the core pipeline (`add-photos.sh`, `extract-photo-metadata.sh`, `build-jpegli.sh`): `add-car-photo.sh` (one resto-mod reference photo into the dual AVIF+JPG pair the car-link tooltips expect, output `holding/cars/<stem>.{avif,jpg}`, no EXIF/R2); `gen-alt-text.py` (AI alt text for every grid photo via the cf-garage Workers-AI caption endpoint, writes `holding/images/alt.json` `{stem: alt}`, resumable); `gen-encoding-samples.sh` (regenerates the color sample set for the `/garage/encoding` study through every encoder, prints byte counts + bytes-per-pixel); `reencode-thumbnails.sh` (re-encodes all published grid thumbnails as pre-cropped center squares from the canonical source folder, two square tiers); `photo-histograms.py` (kept on disk but unused: histograms are now computed client-side). |

### The photo pipeline

Expand All @@ -82,9 +85,11 @@ holding/images/<stem>.{avif,jpg} + R2 aadhar-photos/<filename>
| pulls Fuji recipe (FilmMode, DynamicRange, ColorChrome FX +Blue,
| Grain roughness + size, tone curves, saturation) plus standard
| exposure / focus / metering / WB shift / Kelvin temperature.
| also calls photo-histograms.py to compute a 64-bin luminance
| histogram per photo, inlined as `histogram: [int...]` so the
| Fuji LCD tooltip can draw real bars on hover.
| also writes per-photo /images/meta/<stem>.json files (what the
| tooltip actually fetches on hover). histograms are NO LONGER
| stored — the Fuji LCD tooltip computes the 64-bin luminance
| histogram client-side from the on-screen thumbnail
| (photo-histograms.py is kept on disk but unused).
| discipline: every field is nullable; the tooltip skips lines
| that are null rather than fabricate. never guess metadata.
```
Expand All @@ -100,11 +105,8 @@ Two encoders + one transform tool, all built from source:
primary AVIF thumbnail. Falls back to `sips -s format avif` (macOS
native, no extra dep) when avifenc isn't installed.
- **exiftool, jq** (`brew install exiftool jq`) — metadata extraction.
- **Pillow** (`pip3 install --user pillow`) — per-photo luminance
histograms via `holding/scripts/photo-histograms.py`. optional;
extract-photo-metadata.sh silently skips histograms if Pillow isn't
installed, and the Fuji LCD tooltip falls back to a CSS-gradient
placeholder.
- **Pillow** — no longer needed: histograms are computed client-side
from the thumbnail; `photo-histograms.py` is kept on disk but unused.

### `<picture>` + cache-busting strategy

Expand All @@ -121,7 +123,7 @@ Photo thumbnails are dual-encoded AVIF + JPG, served via `<picture>`:

**The `?v=N` query is critical.** Cloudflare's edge will cache a 404
response for 4 hours if any URL gets hit during a deploy race window.
The `THUMB_VERSION` constant (top of `_worker.js`, currently `10`) is
The `THUMB_VERSION` constant (top of `_worker.js`, currently `18`) is
appended as `?v=N` to every thumbnail URL in the pre-rendered HTML.
**Bump it whenever you suspect cache poisoning** — bumping = fresh URLs =
fresh edge cache lookup = bypass any poisoned 404.
Expand All @@ -140,7 +142,7 @@ and uses `HTMLRewriter` to inject them into the static HTML:
`embed/track/<id>` (for album cover + artist IDs), then
`embed/artist/<id>` (for artist profile pics, KV-cached 30d).
Identifies as `AadharshBot/1.0 (+https://aadhar.sh/bot)` UA.
2. **Photo grid** — random 9 from manifest, emitted as
2. **Photo grid** — random 12 from manifest, emitted as
`<a><picture><source><img></picture></a>` slots inside `<section class="photos">`.

If either chunk fails (KV empty, R2 missing, etc.), the rewriter silently
Expand Down Expand Up @@ -180,13 +182,13 @@ the site doesn't actually serve. To verify:
playlist tracks, photo manifest, artist profile pics, and a few crawler
results. ~10K writes/day budget; we use a handful.
- **PHOTOS_R2** — R2 bucket `aadhar-photos`, holds the SOOC originals
(~3 GB / 120 photos at FUJIFILM X-T5 + Leica resolution).
(~3 GB / 146 photos at FUJIFILM X-T5 + Leica resolution).
- **ASSETS** — auto-bound by Pages, serves static files from the project.

### XP visual vocabulary (CSS)

**Design system:** [`design/DESIGN.md`](design/DESIGN.md) is the Luna brief (canonical
reference + DON'T-modernize guardrails); [`design/tokens.css`](design/tokens.css) is the
reference + DON'T-modernize guardrails); [`design/tokens/`](design/tokens/) is the
canonical token set (fonts, Luna palette, bevels, radii). Pull from those before
hardcoding any color/font/bevel. Captions = Trebuchet MS, UI/body = Tahoma→Verdana,
mono = Courier New — those three stacks only.
Expand Down Expand Up @@ -354,8 +356,6 @@ curated this folder; treat it as the canonical photo source.
worktree still exists (branched off `oddharsh/serendipity` on GitHub). It
has the same code in it but is no longer the source of truth. Future work
should happen in this directory.
- No GitHub remote yet — user wants this to be a private repo eventually.
Run `gh repo create aadhar-sh --private --source=. --remote=origin --push`
when ready.
- The GitHub remote exists: `origin` points at `git@github.com:oddharsh/site.git`.
- `node_modules/`, `.wrangler/` build cache, and `.DS_Store` files were
intentionally not copied. They'll regenerate as needed.
Loading