Loading…
a327ex.com

Anchor Website 8

Opus 4.8

Summary

Per-post fidelity pass on the in-engine a327ex.com renderer (a327ex-site/renderer/). The user went through posts one-by-one against the live site, reporting issues; each was fixed in turn. Session ended mid-pass (context window) — the immediate next step is running fetch_media.py for the now-wired auto-generated YouTube CC + postering the converted mockup videos.

Old /posts/* layout — drop the sidebar + clickable crumb:

  • On the live site old Blot posts render WITHOUT the sidebar (skip_crumbs + the Blot header bar); the renderer kept the sidebar. Added content_view() in main.lua returning (content_x, content_w, show_sidebar); old posts use a centered Blot container, draw()/relayout()/wheel routing gate on show_sidebar.
  • The home / section / slug crumb became a dedicated {type='crumb'} element (elements.lua layout/draw_crumb_element, canvas.lua dispatch); "home" is clickable → show_home(), hit-tested in update() from the laid-out element + scroll. Removed the dead kind=='crumb' text branches.
  • Follow-ups: dead-centered the old-post column (was Blot-faithful left-of-center, user wanted centered); fixed videos auto-playing through the navigation (the navigating click bled into the new page's poster hit-test — consume ui_mouse_pressed=false in load_page/show_home); underlined "home"; added date+time top-right on the crumb line (looked up from the index, fmt_crumb_date).

Clickable inline links (engine + renderer): user chose Option A (engine binding) over os.execute. Added open_urlSDL_OpenURL in Anchor2 anchor.c. Renderer: tokenizer carries url onto word/ws tokens; _link_rects (per-line merged) built in layout_text_element; canvas_link_at walks text elements; open_link dispatches internal (a327ex.com/anchor.blot.im or /section/slug whose slug exists) → load_page, external → open_url. Click consumed so it can't bleed into video/lightbox.

Whole-site link audit: extracted 1310 real hyperlinks from the data files (excludes code-block text), classified internal/external, HTTP-checked 515 unique externals, then HAND-VERIFIED suspects (raw HTTP status is unreliable — claude.ai/X/steamdb/github bot-block). Tooling left in renderer/tools/ (extract_links.lua → classify_links.py → audit_report.py → make_report.py); report in renderer/reference/link_audit.md. Fixes applied (user: "fix what you're sure about, surface doubts"): howtomarketyourgame.com (500/dead) → howtomarketagame.com (verified 200); opus-4.5 ×6 download links — dot-vs-hyphen path, relinked /media/notes/opus-4.5//media/notes/opus-4-5/; 7 deleted tweets (syndication-API-verified TweetTombstone) → 4 with wayback snapshots repointed, 3 with no archive had the dead link removed (anchor text kept; @stimhacked's ::tweet embed directive kept its original URL); gamasutra article gone → web.archive.org snapshot; explorer.helium.com→world.helium.com, rendertoken→rendernetwork, goldenlight.mirror.xyz→ paragraph.com, boards.4channel.org→4chan.org; rumbleverse (defunct) → Wikipedia. Left per user: new.a327ex.com (DNS-dead, fine in context), /posts/the_haircutter (fine broken). Also stripped 71 code-junk self-links ([e.target](http://e.target), h.id, plan.md, …) from the logs via an explicit denylist (real [domain/path](url) self-links like claude.ai/amulet.xyz preserved).

Inline emphasis parser rewrite (the ::sidenote "edit from the future" asides): links inside _italic_ rendered as literal [text](url) and _vs_ in a URL (TYRONE_vs_COPS) closed the italic early. Root cause: parse_inline was a flat single-pass scanner with no recursion. Rewrote it: added find_emph_close (skips [...](...) and `code` when seeking an emphasis closer) and made emphasis spans RECURSE (inline() + style-merge), so nested links/bold parse and inherit the outer style. Verified simple cases unchanged. Reconverted all 349 pages; a site-wide sweep found 0 remaining literal ](http…) links.

Sidebar + navigation: added SEC_BODY_GAP (header→entries breathing room). Added n/p next/prev-post keys — chronological order (reversed index → small_games oldest [1] … newest message [N]); from the homepage next→first, prev→last; clamps; load_page now also clears the lightbox.

Old-skin heading spacing (two attempts): first head_shrink (top-aligned box trim) only tightened the gap below — insufficient ("extreme height differences still haven't been fixed"). Replaced with head_overflow (centered overflow): shrink the old-theme h2/h3 box by 2*overflow and draw the glyph CENTERED in it (overflowing top+bottom), replicating old-blog.css's line-height:8px. Gaps tighten both sides and become independent of font metrics; gap_before back to 48. h1 untouched (its line-height:36px was already roomy); new theme head_overflow=0. Draw applies el._head_oy in draw_text_element.

Image lightbox crispness: a centered odd-dimension image landed on a half-pixel, so the smooth filter blurred an otherwise 1:1 texture (article images are crisp because el.x is an integer left edge). Fixed by pixel-snapping the lightbox top-left.

YouTube title + open-on-YouTube: youtube_url(el) (watch?v= / shorts/), draw_video_title (gradient scrim + title at top of frame, always on the poster + on hover during playback, scales in fullscreen). Click the title → opens the video on YouTube (open_url). Active-video title click wired in video_controls_update. The not-downloaded placeholder for youtube/short now reads "click to watch on YouTube" and the card opens YT — so the 8 unrecoverable embeds are useful again.

Playback speed controls: new engine binding video_set_speedma_sound_set_pitch (the video clock follows audio consumption, so A/V stays synced; PITCH-SHIFTED — pitch-correction deferred as a separate DSP lift). UI: a 1x speed button on the controls bar + a popup menu (0.5/1/1.25/1.5/2×, speed_menu_geom mirroring the cc menu); persists across videos. Engine rebuilt; binary copy was blocked while the renderer ran, copied successfully at end of session.

Auto-generated CC — WIRED, NOT YET PULLED (the explicit NEXT step): fetch_media.py's make_subs now also fetches YouTube auto-subs (--write-auto-subs, English-only en.* to avoid the ~50-language auto-translation explosion) into a separate subs/auto/ dir, keyed "<lang> (auto)" in the manifest (only filling gaps where there's no human track), behind a versioned .subs2.done marker. subs_parse got a dedup pass (drop empty + collapse consecutive duplicates of the rolling word-by-word cues). video_load_subs prefers human en, then en (auto). ⏳ The user must re-run python tools/fetch_media.py (network — YouTube anti-bot) to actually pull them; cleanup is a first pass to refine once the real auto-VTT is seen.

marketing_skills "missing content": the raw <div class="captioned-image-container"> rendered as literal text — convert.lua now strips lone raw-HTML block tags (applied site-wide). The animated UI mockups used ::image pointing at .mp4/.webm files (broken even on the live site as <img src=x.mp4>) — fixed the author's directive mistake by changing those 4 to ::video (across marketing_skills, self_expression_vesselization, unity_godot_artists_money); they now convert to video elements and reuse the local-video pipeline (need fetch_media to poster them; side-by-side captioned layout not reproduced — they stack).

New-tab links (note only): the web build must open EVERY link — including internal/same-site — in a new tab (target="_blank"); recorded as a WEB-PORT NOTE on open_link and in PLAN.md. Desktop behavior unchanged (internal → in-app nav is the desktop equivalent).

Files touched: renderer/main.lua, elements.lua, theme.lua, canvas.lua, sidebar.lua, tools/convert.lua, tools/fetch_media.py (+ audit scripts), reference/link_audit.md, PLAN.md; Anchor2/engine/src/anchor.c (open_url + video_set_speed); source edits across ~18 posts + self-link cleanup in several logs. All 349 pages reconverted. PLAN.md has a prominent ⏸ MID-PER-POST-FIDELITY note with the fetch_media-for-auto-CC next step.

🔒 Only the summary of this log is public. Private because it contains too many website internal details.