The site redesign — state, decisions and where everything is (2026-09-13)
Read this before touching the Reading theme, the reader, the collections or the notebook. It is the handover from the session "Website Redesign 1" (2026-09-12/13, omni, gated log): what was decided and why, what was built and where, what is gated, what is known to be missing, and how to test it. PLAN.md's top three sections (site_next, the reader, phase B) are the implementers' own notes and go deeper on code; this file is the map.
1. What this is, in one paragraph
The owner wants a327ex.com to feel organized and purposeful instead of a feed, with books
presented Kindle-like (two facing pages, horizontal turns) and books and games mixed. The
thread produced: a 51-mockup board (Fable + Astra), a codified dark theme kit (THEME.md +
eight sheets), and three Opus 5 implementation runs that built the whole thing into the
renderer as an OPT-IN theme called Reading (site_next in code). Nothing about the
default site changed for visitors. The redesign is committed (be030a7 and the two commits
after it) and deployed, but gated: visitors on the web cannot select the Reading theme.
2. Where things are
| What | Where |
|---|---|
| This map | renderer/REDESIGN.md |
| Implementer notes per run (code-level) | renderer/PLAN.md, top three sections |
| The theme kit (authoritative values) | renderer/reference/site-theme-2026-09-13/THEME.md + sheets 01-*.png … 08-*.png, index.md |
| The 51 mockups and the board | renderer/reference/redesign-2026-09-12/ (gallery.html, index.md, index-2.md, web/*.jpg; the PNGs are local-only, gitignored) |
| The Ricochet exemplar the kit copied | renderer/reference/ricochet-exemplar/ricochet-design.md (sheets local-only; originals on Z:\2025-2026\code\a327ex-linux-2026-09\from-hdd\Ricochet\reference\) |
| Verification snapshots (local-only) | renderer/reference/site-theme-2026-09-13/snaps/, snaps-reader/, snaps-collections/ |
| The delegation packets and reports | Anchor/workflow/delegate/runs/20260912-site-redesign-astra-opinion/ (Astra: discussion, images, kit; thirteen turns), 20260913-site-theme-build/, 20260913-site-reader/, 20260913-site-collections/ (Opus 5; each has brief.md = the contract and report.md = what was done, with every decision the implementer made) |
| New renderer modules | renderer/reader.lua, renderer/works.lua, renderer/collections.lua, renderer/notebook.lua |
| Changed renderer files | theme.lua, main.lua, elements.lua, canvas.lua, homepage.lua, sidebar.lua, search.lua, tools/build-web.sh, tools/deploy.sh |
3. The design conclusions (why things are the way they are)
From the Fable/Astra discussion (round two settled most of it; the mockups tested it):
- Choosing, reading sequentially and consulting are the governing distinction, not "stock versus flow". The front door is for choosing; the reader is for sequential reading; logs plus search are for consulting. That is why logs still scroll while stories, essays and the notebook page.
- Works get lasting homes. A book and its game are one work; the home holds the thing, its development history (the log series) and related essays. This is the seed of the future "one story = novel + game" presentation.
- Pages are windows onto the single-column layout. No second layout engine: the reader computes break offsets at text-line and element boundaries and draws each page by translating and clipping the column. Every element draw, selection, find and link hit-test keeps working in column coordinates. This is the architectural decision that made the build cheap and safe.
- The round-one readers looked "lacking" because their pages were empty. Real text at a book measure in the same chrome reads as a book. Pages must be full.
- Position addresses and citation addresses are different things. The reader remembers a place by element-and-line ordinal (per device); page numbers are never in URLs; persistent block ids for public citations are future work.
- Gold locates, blue acts. Gold is only for the current item, entry ids and progress. Artifact and replay links became blue under the theme.
- The notebook is a book whose chapters are months (mockup 34): the untitled posts paged in the reader's chrome, newest first, days as the contents overlay.
- The daily broadsheet was dropped (a day is an arbitrary layout budget) in favor of the paginated notebook.
- Instant cut on page turn, no curl, no paper. Wheel flick turns one page (debounced); edge zones only in the free outer margins; clicking on a page never turns it.
- Mock-up decisions the owner made (2026-09-12): front door = image 5 (works + notebook column), reader = 7 (then 28 v2), notebook = 12/34, work homes 15/16/40/41, logs 17/45, replay 21/42/48. The dark theme of those images is the theme. He said the sidebar is unnecessary and text can be smaller.
4. The theme (run 1: 20260913-site-theme-build)
THEMES.site_nextintheme.lua, with its ownFONTS_NEXT / METRICS_NEXT / GAP_BEFORE_NEXT / TREAT_NEXT; switching to or from it relayouts (likeposts_old). Type scale per THEME.md: page title 32/40, item title 18/24, body 16/24, UI 14/20, meta 12/16, section label Segoe UI Semibold 12/16 tracked 1.2, ids/paths Cascadia 12/16, code 14/20, h1/h2/h3 28/21/16. Arial 700 stands in for every 600 the kit asks of Arial; the only true 600 is the section label. Metrics: the scrolling article keepscolumn_w 800 / text_w 704;body_line_height 1.5; gaps h1 24, h2 24, h3 16, image 16, quote 24;heading_rule = false.- Fourteen new color keys exist in EVERY theme (
panel, recess, control_border, link_hover, link_pressed, current, focus, hover_wash, current_wash, on_accent, overlay, warning, text_secondary, text_dim), derived from each theme's own palette, so drawing code can read them under any theme. - Chrome under the theme: no sidebar; a 64 px top line (
NAV.draw_barinmain.lua) with the brand, the section links, a search affordance and settings · privacy · archive. Mobile chrome (the 44 px bar + hamburger) is unchanged under every theme. - Element treatments under the theme only: pill chips (
chip_metrics / draw_chip / chip_colorsinelements.lua, shared by the log page and the homepage), hover-only link underlines, no heading rules, blockquote rule 1 px / role bar 3 px (canvas_theme_sync), mediacard as a 64 px file row with an outlined Open pill, tweet card as a rounded panel (padding 16, avatar 32, radius 8), code blocks in therecesswell,small_italicupright (metadata is not italic in this theme). - Selection: settings stepper Dark / Light / Reading, F2 cycles the same order, the
persisted setting accepts the theme,
A327EX_THEME=nexton desktop overrides for a run. site_debugglobals inmain.luafor headless drives:theme(name),nav(path),view(),snap(path),state(),reader(cmd, arg),collection,scroll.- Left alone on purpose: per-role line boxes and a separate reading scale (the renderer has one shared line gap), letter tracking outside the section label (the engine's text has no tracking), the collapsed tool rows, log-turn speaker typography, focus rings (no keyboard focus model), the Aa reading-settings popover, the serif for book prose.
- Known nits: the admin pageviews readout collides with the top bar under the theme; the scrollbar overlaps the bar's right end by a few px; nav labels are capitalized while the trailing cluster is lowercase.
5. The reader (run 2: 20260913-site-reader) — renderer/reader.lua
- Entry point:
reader_wants(d, theme, pref)/reader_doc_pages(d): a story or a titled post (essay), undersite_next, with the "Reading layout" setting on Pages (default). Old-Blot docs (Theme: old, 42 of them, every pre-2023 file, including It Follows, Luck isn't real and Status addicts) DO page and render in the theme when paged; in Scroll mode or under Dark/Light they keep their old skin. The brief had excluded them; the implementer resolved it toward the verification set, one condition infinish_load_pageplus its mirror inreader_sync. - Geometry (THEME.md "Reading geometry"): spread from 1120 px, page width
min(624, (W - 2*outer - 32)/2), gutter 32, measuremin(528, page - 64), outer margin 48/32/16 by breakpoint, header 64, chapter strip 64 (when 2+ h1s), gaps 24, footer 48, page numbers 32 above the page bottom. It Follows: 252 pages at 1920x1080, 283 at 900x1000, ~300 ms to lay out and break;breaks_ok(a programmatic check that no line is cut) is true. - Atoms and breaks: one atom per laid-out text line (
el._linesalready carried y and height), one per non-text element; containers are not atoms. Greedy fill with widow and orphan control, headings keep two lines, the ending reserves 112 px on the last page, trailing blank atoms dropped. A code block is ONE atom (revisit if paginated logs land). Oversized atoms get their own page scaled through the layer transform; video and games are never scaled (cut at the page bottom); a scaled page is not hit-tested. - Clipping by culling (a line is on the page if its midpoint is inside the band), not by stencil (the engine's stencil is one global flag that code and video already use).
- Chrome: the top bar shows brand, work title, Contents; chapter strip for chaptered
works (current in gold with real progress; names dropped below 104 px per cell); footer
Previous / "Chapter N of M" or "page N of M" / Next; the ending block ("END OF
", Contents, Return home); the contents overlay (headings with page numbers; the notebook swaps in a Dates overlay). - Input: arrows, PageUp/Down, Space and Shift+Space, Home/End; Previous/Next; edge
zones in the free outer margins (48 px, hover wash + chevron); wheel flick = one page
(accumulates 40 px, 250 ms dead time, stray notches decay); swipe on mobile only (48 px
horizontal, 1.5x the vertical). Esc closes overlays. A cut, no animation (the hook is
reader_goto_page). - Position memory:
{e = element index, l = line index}per doc slug, inrenderer/positions.luaon desktop (gitignored) anda327ex_positionsin web storage, debounced 1 s, restored on open; a reflow keeps the place.#fragmentopens the page with the heading;?q=opens the page with the first match. - Mobile: single page, the existing 44 px bar with Back and the title, footer controls 44 high.
- Not built: the Aa popover, the edge-preview tooltip, slide animation, the serif.
tools/build-web.shpreloadsreader.lua(and the phase B modules); a module missing from that list kills the web boot onrequire(PLAN.md's lesson, and how the live site broke on 2026-09-13).
6. Collections, homes, front door, notebook, log frame (run 3: 20260913-site-collections)
works.lua: the hand-maintainedWORKStable (It Follows story 2025 Read; SNKRX game 2021 Steam; BYTEPATH game 2018 Steam; Horse Game prototype 2026 Play, series{'Horse Game', 'ABA Games Variations — KNIGHT VS. PAWNS'}; Skyland prototype 2026 Play, series'3D Exploration — Skyland'),EXPERIMENT_SERIES(3D Exploration, ABA Games Variations, Character Exploration, Emoji Ball Bounce Exploration, Environment Exploration, Fable Test, Kimi Test, Lookdev, Meso Exam Exploration, Reverse Minesweeper Prototype, Sketches, Visual Experiments; Fable Test and Kimi Test are the arguable rows),series_name_of(title minus trailing number),works_init(index)and the query functions. Session numbers are ordinals ("Horse Game 22" is session 14 of 14) because the title numbering skips. No summary is invented: It Follows uses its first paragraph, Skyland has none, Horse Game opts out, SNKRX/BYTEPATH have no document.archiveandprivacyare excluded from essays.relatedis empty everywhere (THEME.md forbids invented associations). This table is the owner's to edit.- Routes (
nav_to_pathinmain.lua, site_next only; other themes land home):/front door,/works,/works/<slug>,/notebook,/essays,/experiments,/logs(the matrix). The top line is Works · Notebook · Essays · Experiments · AI Logs · Search. There are NO server-side routes or crawler HTML for these yet: a hard reload of/workson the web 404s. That is the first follow-up. - Front door (
collections.lua): works column 38 % with the Continue band (remembered positions from the reader, hidden when empty), the work rows (typographic 64x96 covers, no cover art exists), and Essays / Experiments / AI Logs modules with their newest two items; notebook column 62 % with the newest entries' whole bodies (header above the body: gold mono id, date, tags). No filter chips on the front door. Below 1024 the works become a row of covers above the notebook; on a phone it stacks. - Work homes: 160x240 cover, title, kind/year, summary, filled primary action, Resume
with the saved place, Contents (stories: the h1 list, click opens the reader at that
chapter, gold bookmark), Development history (the series, newest first, "View all N
sessions" to
/logs?series=), Related (hidden when empty). The game is NOT hosted in the home: hosting the prototype's game element in another page paints the game over the whole window regardless of the composite rect (the cause is ingame_hostor the game package); Play opens the prototype page instead. - Notebook (
notebook.lua): the 182 untitled posts as ONE document, newest first, a month heading marked_chapterwhen the month changes, an entry header element (id in gold Cascadia linking to the permalink, date, tags), the entry's own elements as the feed builds them (entry_doc_new), an hr between entries; the reader takes it with no special case (250 pages), slugnotebook. Dates overlay = the month's days with their ids. No filter chips on the notebook in this build. - Permalink (
/posts/<timestamp slug>under the theme): the entry alone, centered, with "<- #528 · Return to notebook · #530 ->" by id order. - Essays: titled posts by year with date, "~N min read" (ceil(words/200)), the real first sentence (skipping a byline element). Old-Blot titled posts are listed and page. The numbered fragment posts (000000, 170011, …) are titled, so they appear here too.
- Experiments: cards (panel, radius 8) for the two prototypes (filled Play) and the 35
logs whose series is in
EXPERIMENT_SERIES(outlined View); chips All / Playable / Logs. - AI Logs: months (newest first) × the six biggest series + Other; a cell lists up to two sessions and "+k more"; clicking a cell expands its list below. The matrix is sparse (Other holds 204 of 274 logs); top-series-per-month would fill it better.
- Log frame: under a log's title, "
· session N of M · ", Previous / Next session, "Part of " (or "All sessions" to the matrix). The transcript keeps scrolling. - Search: results grouped under Works / Essays / Notebook / AI Logs; a work result opens its home. Sheet 50's preview panel is not built.
- The one change outside the theme:
tools/convert.luanever wrote theuntitledflag, so untitled posts opened with their first sentence repeated as an h1 under every theme, and the reader took them for essays.finish_load_pagenow stamps the flag back from the index; the real fix is one line in the converter (serialize()). - Gaps: text selection and find are off on the front door and the collection pages (the
paged notebook is a normal document and has both); the mobile hamburger still lists the
old sections (
sidebar.luauntouched by run 3);/logshas no month-range control.
7. The gate
Visitors on the web must not see the in-work site. theme_gate_open() in main.lua
(next to THEME_ORDER) is true on the desktop build and on a web device holding the admin
token (pageviews_admin()); otherwise the F2 cycle and the stepper hold Dark / Light, a
persisted site_next is clamped back to Dark at boot (settings_load), and the collection
routes land on the homepage. To ship the redesign, remove the web condition in that one
function. The admin token is polled from web_boot_param('adminToken') every 60 frames, so
on an admin device the first boot may clamp a persisted Reading to Dark once; re-select it.
8. How to see it (desktop)
cd a327ex-site\rendererthenrun.bat(orA327EX_THEME=next run.bat).- F2 until the theme reads Reading, or settings > Theme > Reading. Settings > Reading layout: Pages (default) / Scroll.
- Front door; the top line; Works > a home; Notebook (months strip, Dates overlay, gold ids); Essays; Experiments; AI Logs (click a cell); Search "snkrx"; a log page's series frame; a story or essay in the reader (arrows, Space, wheel flick, edge zones, Contents, the ending, resize below 1120 for one page).
- F2 back to Dark: the old site, unchanged.
renderer/positions.luaholds remembered places (delete to clear the Continue band).
9. How to verify mechanically (never by running interactively)
- Syntax:
Anchor/workflow/tools/lua54.exe -e "assert(loadfile('renderer/<f>.lua'))". - Test:
lua54.exe renderer/tests/attribution.luafroma327ex-site/. - Headless:
python Anchor/workflow/anchor.py drive start a327ex-site/renderer, thendrive eval a327ex-site/renderer "site_debug.theme('site_next') site_debug.nav('/works') engine_step(60) site_debug.snap('<png>') return site_debug.state()", thendrive stop.site_debug.reader()returns page / pages / spread / breaks_ok / atoms / chapters / layout_ms. Snapshots are 1920x1080 PNGs you can Read. - Web:
bash renderer/tools/build-web.shthenpython renderer/tools/serve-web.py 8000(the.claude/launch.json"renderer-web" entry opens it in the app browser); check the console for "Loading: main.lua" and no errors. F2 does not reach the canvas through the automation; use the settings page by clicking. - Deploy:
renderer/tools/deploy.sh --content. It now REFUSES an uncommitted renderer (tracked edits or untracked new modules) unless--allow-dirty, because on 2026-09-13 another session'sanchor msgdeployed the half-built tree and broke the live boot (works.luawas required but not preloaded). The last-good bundle from before the redesign is kept on the VPS at/srv/a327ex/render/keep/(its loaderrenderer.jswas overwritten, so it cannot simply be re-pointed).
10. What to do next (suggested order)
- The owner judges the build in
run.batand lists changes. - Server-side routes and crawler HTML for
/works,/works/<slug>,/notebook,/essays,/experiments,/logs(server/content.lua + server.lua + seo.lua), so a hard reload works and crawlers see the collections. - The converter's
untitledflag (one line intools/convert.luaserialize()). - The game hosted inside its work home (
game_host.lua: it paints over the page when the host is not the page itself). - Mobile: the hamburger's sections under the theme; selection and find on the collection pages; the Aa popover; persistent block ids for citations; the edge-preview tooltip.
- Cover art per work (the 64x96 typographic cover breaks long titles by character).
- Ship: remove the web condition in
theme_gate_open(), or make Reading the default.
11. How the work was done (for the delegation record)
Fable directed; Astra (Codex, gpt-6-astra, xhigh) did the discussion rounds, all 59 images
and THEME.md in one thread (anchor delegate followup now drives such threads); three
Opus 5 subagents at extra effort implemented under packets (brief + scope + stop
conditions + verification + report), each reviewed by Fable through the diff, a re-run of
the checks and the headless snapshots. Each run's report.md lists every decision the
implementer made on its own; brief.md is what it was asked. The mockup board is
gallery.html in the mockups folder (also published as a claude.ai artifact during the
session).