Feature Map

featuresinteractionsUI

Source: /Users/weixiangzhang/Local_Dev/projects/bythewei/src/pages/index.astro Stack: Astro 5, vanilla JS, no framework — single-page app with three modal experiences Last audited: Feb 19, 2026


1. Page Sections

The page is a cork board (div.wall) with sticky notes, pins, tape, and kaomoji faces. The entire visual metaphor is a developer’s sprint board pinned to a physical cork wall.

1.1 Banner Header

Location: top of .wall
Element: div.banner
  • Dark navy background (#1a1a2e) with gold (#F0B847) text
  • Title pulled from sprint.meta.title (currently “VOXLIGHT — FEB 18 SPRINT”)
  • Subtitle from sprint.meta.subtitle (“One founder. One day. One gate left.”)
  • Three decorative pins: red (left), yellow (center), blue (right) — purely visual
  • Two kaomoji spans flanking the title, rotated daily by the kaomoji engine
  • Slight -0.3deg rotation for the “pinned at an angle” effect
  • Gold border (box-shadow outline)

1.2 Stats Bar

Location: below banner
Element: div.stats-bar
Data: sprint.stats[] array from sprint.json
  • Horizontal row of stat-card elements, centered with flex-wrap
  • Each card shows a value (large, gold, Fredoka font) and a label (small, gray, Kalam font)
  • First card has a leading kaomoji; last card has a trailing kaomoji
  • Current stats: 111 tests passing, 520 SyncEngine lines, 542 Shortcuts spec, 1.1K Threads views, 12 docs written, 4 repos clean, 26K Guilty Gear RP
  • Navy background cards with gold text, matching the banner aesthetic

1.3 QOTD (Quote of the Day) Card

Location: below stats bar
Element: div.qotd-wrap > div.qotd-card
Data: fetched from /data/bookmarks.clean.json at runtime
  • Label: “QUOTE OF THE DAY” with pin emoji and kaomoji
  • Card styled as a cream-colored note with gold left border, tape strip on top, corner fold on bottom-right
  • Loading state: “loading today’s passage…” with bear kaomoji
  • Error state: “quote escaped. check back tomorrow.”
  • Selection algorithm: Date-seeded hash (same quote for all visitors on the same day). Filters to entries with highlights > 30 characters, then uses hashPick() with a Knuth multiplicative hash
  • Content:
    • blockquote.qotd-text — the highlight passage with decorative curly quotes (CSS ::before/::after)
    • button.qotd-book — book title (clickable, dotted underline, gold accent)
    • span.qotd-author — prefixed with em-dash
    • span.qotd-date — pill-shaped date badge, right-aligned
  • Changes daily at midnight without deploy

1.4 Sprint Board Columns (5 Columns)

Location: center of page
Element: div.columns (CSS grid, 5 columns at full width)
Data: sprint.columns[] from sprint.json

Each column has a header (.column-header) and N sticky notes. The five columns are:

ColumnHeaderContent
1SHIPPED CODESyncEngine, Chapter Index Remap, Bridge.js, Liquid Glass, Tab Bar Polish
2TESTS & QUALITY47 Unit Tests, Fleet Audit, Opus Arch Review, UI Bug Fixes, Test Infrastructure
3THE GATEE2E Sync Test (blocker), Pass Criteria, After Gate Passes
4DOCS & STRATEGY12 Docs Written, Shortcuts Spec, 4 Repos Clean, Apple Intelligence Brief
5MARKETINGBlog Post LIVE, Threads Posts, LinkedIn Sequencing, Bio Updated, Reddit (Queued)

Sticky note anatomy:

  • Color class: y (yellow), g (green), p (purple), b (blue), o (orange), r (red), w (white), teal
  • Rotation class: r1 through r7 (-2.3deg to +2.1deg)
  • Optional big size class for larger stickies
  • Optional blocker class (red border + red glow)
  • Optional tape strip (center, left, or right positioned)
  • Optional stamp: “DONE” (green) or “IN PROGRESS” / other (orange, .wip)
  • .sticky-title (bold), .sticky-body (pre-line whitespace), .sticky-tag (pill badge)
  • Hover: scales to 1.02 and straightens rotation to 0deg

Responsive: collapses to 3 columns at 1100px, 2 columns at 700px.

1.5 Bottom Row Stickies

Location: below columns
Element: div.bottom-row
Data: sprint.bottom_row[] from sprint.json
  • Horizontal flex row, centered, wrapping
  • Max-width 220px per sticky, slightly smaller font (0.9rem)
  • Five stickies: Guilty Gear, Reading: Futureland, Insight of the Day, Runway, Agents Used
  • Same sticky styling as column stickies but without stamps or blocker styling
  • These are “ambient life” notes — gaming, reading, finance, meta-tools
Location: below bottom row
Element: div.find-me-header + div.find-me

Header with bear kaomojis flanking the text. Below it, a flex row of 8 link stickies:

StickyTypeURLColor
simplephilosopher<a>simplephilosopher.comyellow
storiesbywei<a>storiesbywei.comteal
@maybe_foucault<a>threads.com/@maybe_foucaultpurple
noxwei<a>github.com/noxweiwhite
not_foucault<a>instagram.com/not_foucaultorange
Zato-1 puddle.farm<a>puddle.farm/player/…red
goodreads<a>goodreads.com/user/show/4258173green
150 books in one year<button>Opens Reading Year modalwhite
  • All <a> links open in new tab (target="_blank", rel="noopener")
  • All have .link-sticky class: wavy underline on title, 200px max-width
  • Hover: scales to 1.06 and straightens rotation
  • The “150 books” button is the only <button> in this row; it triggers the Reading Year modal
Location: bottom of .wall
Element: div.footer
  • Centered text: “WEIXIANG INC . BYTHEWEI.DEV . FEB 18 2026 . ONE GATE LEFT” (from sprint.footer)
  • Followed by a kaomoji
  • Semi-transparent white (0.5 opacity), Fredoka font, 2px letter-spacing

1.8 Hidden Shelf Trigger

Location: fixed, bottom-right corner of viewport
Element: button#shelf-trigger
  • A single pushpin emoji: 📌
  • 25% opacity at rest, grayscale filter — intentionally near-invisible
  • Hover: 60% opacity, -8deg rotation, 1.15x scale
  • aria-label="?" — intentionally cryptic
  • Fixed positioning, z-index 50
  • Clicking opens the Card Catalog modal

1.9 “150 Books in One Year” Sticky Trigger

Location: last item in the "WHO IS THIS GUY" section
Element: button#reading-trigger
  • Styled identically to the link stickies but is a <button> element
  • Title: “150 books in one year”
  • Body: “the year i read everything. emotions, genres, & strong opinions.”
  • Tag: “2019-2020”
  • White color, r5 rotation
  • Clicking opens the Reading Year modal

2. Modal Experiences

All three modals share common infrastructure:

  • div.modal-backdrop with hidden attribute, aria-modal="true", role="dialog"
  • Backdrop: black 65% opacity + 3px blur
  • Click on backdrop (outside modal content) closes the modal
  • Escape key closes modals (see section 3)
  • Opening any modal sets document.body.style.overflow = 'hidden' (scroll lock)
  • Closing restores scroll
  • Entry animation: modal-in (translateY -16px to 0, opacity 0 to 1, 0.25s ease)

2.1 The Catalog (Bookshelf Modal)

Trigger: button#shelf-trigger (the hidden pin 📌)
Element: div#catalog-modal
Data: /data/bookmarks.clean.json (same data as QOTD, cached in allEntries[])

Visual design: A dark wooden bookcase (#3d2510 to #1f0e05 gradient) with gold trim. Title “THE CATALOG” in Permanent Marker, subtitle “everything i’ve marked in the margins” in Kalam.

Content — Bookcase:

  • Books are grouped by title using groupBooks(): entries deduplicated by normalized title (lowercase, alphanumeric only, first 40 chars)
  • Sorted by annotation count (most annotated first)
  • Books packed into shelf rows based on available width (clientWidth or 1060px default)
  • Each row: .shelf-spines (flex container) + .shelf-plank (wooden shelf with wood grain texture, drop shadow, highlight)

Individual book spines (button.book-spine):

  • Width varies by annotation count: 40px (0-2), 48px (3-10), 56px (11-25), 64px (26-60), 72px (61+)
  • Color tiers by annotation density:
    • 0 marks: cream (#f0ece0) — ghost
    • 1-2: ivory (#e8d5b5)
    • 3-10: warm tan (#c4956a)
    • 11-25: sienna (#a0522d)
    • 26-60: deep rust (#7a3020)
    • 61+: near-black mahogany (#4a1a1a)
  • Books with 26+ marks get .spine-gold class (diagonal gold shimmer overlay)
  • Title rendered vertically (writing-mode: vertical-rl, rotated 180deg)
  • Small gold dot at bottom with opacity proportional to mark count
  • Hover: rises 18px, slight horizontal scale, brightness boost, large shadow
  • Click: closes catalog, waits 200ms, opens journal for that book

Spine tooltip (.spine-tooltip, single element repositioned by JS):

  • Shows on mouseenter, hides on mouseleave, follows mousemove
  • Content: title, author, mark count with progress bar (scaled to max 91), teaser (shortest highlight > 40 chars, truncated to 100)
  • Positioned relative to mouse cursor, clamped to viewport edges
  • Cream background with gold top border, decorative tape strip
  • pointer-events: none — purely informational

Loading state: “shelving books…” with sleeping kaomoji. If data not yet loaded: “still loading… try again in a sec”

Close: X button (#catalog-close), backdrop click, or Escape key

2.2 Reading Journal

Trigger: clicking a book spine in the catalog, or clicking the QOTD book title button
Element: div#journal-modal
Data: filtered subset of allEntries[] matching the selected book title

Visual design: A physical journal/notebook. Cream paper (#faf8f2) with ruled lines (1.75rem spacing) and a red margin line (at 3rem from left). Dark leather spine on the left side.

Layout (flex row):

  1. Journal spine (40px, dark leather gradient):

    • Back button (#journal-back, gold arrow): closes journal, reopens catalog
    • Ribbon progress bar: gold (#F0B847) bar that fills vertically as user scrolls. Height tracks scroll percentage via scroll event on .journal-pages
    • Page count label (vertical text, very small): “N passages”
  2. Journal pages (#journal-pages, scrollable):

    • Header: book title (Permanent Marker), author (Kalam italic), gold gradient rule
    • Entries (#journal-entries): one .journal-entry per highlight passage
      • Entry number (.je-number): zero-padded, positioned in left margin
      • Date (.je-date): vertical text in the margin area
      • Text (.je-text): full highlight. First sentence gets a gold highlighter effect (.je-first — CSS gradient underline at 55-90% height)
      • Dog-ear button (.je-dogear): invisible by default. On entry hover, shows a gray corner fold (top-right). On click, toggles to gold corner fold. State persisted in localStorage with key de-{title20chars}-{index}
    • Empty state: “no passages found” with sad kaomoji
  3. TOC panel (#journal-toc, initially hidden):

    • Slides out from the left side (positioned absolute, left: 40px)
    • Lists all entries with index number and date
    • Dog-eared entries shown with pushpin emoji and bold gold text
    • Click an entry: smooth-scrolls to that passage in the journal, then hides the TOC
  4. TOC toggle (#toc-toggle): section sign button on the spine edge, rotated -90deg. Toggles TOC panel visibility

  5. Close (#journal-close): X button, top-right

Scroll position persistence: On close, saves journalPages.scrollTop to localStorage with key js-scroll-{title20chars}. On reopen, restores saved position.

2.3 The Reading Year

Trigger: button#reading-trigger ("150 books in one year" sticky)
Element: div#reading-modal
Data: /data/reading-log.json (fetched on first open, lazy-loaded)

Visual design: Dark wooden board (same as catalog). Title “THE READING YEAR” in gold. Subtitle: “150 books . feb 2019 - feb 2020 . 41,086 pages”. Scribble annotation: “41k pages. i regret nothing”

Sections (all inside .reading-content, max-height 72vh, scrollable):

2.3.1 Stats Strip (#reading-stats)

Five cards showing: total books, total pages, average rating, five-star count, genre count. Gold text on dark translucent cards.

2.3.2 Monthly Reading Wall (#reading-wall)

  • Label: “books finished per month”
  • Horizontal flex row, one column per month (Feb ‘19 through Feb ‘20)
  • Each month: vertical stack of colored mini-blocks (.wall-mini), one per book
  • Mini-block color = genre color (from GENRE_COLORS map: Fantasy=#4ecdc4, History=#5dade2, etc.)
  • Each block slightly randomly rotated (-3 to +3 degrees)
  • Title tooltip on each block: “Title — star rating”
  • Month label and book count below each stack
  • Interactive: see section 3 for hover/click behaviors

2.3.3 Genre Bars (#genre-bars)

  • Left panel in a 2-column grid
  • Horizontal bar chart, sorted by count descending
  • Each row: genre label (120px, right-aligned) + bar track + count value
  • Bar fill color matches genre color
  • Highlights on hover interaction (see section 3)

2.3.4 Diversity Bars (#diversity-bars)

  • Right panel, top section
  • Two stacked bar segments:
    • Gender: F (purple #bb8fce) / M (dark blue #2c3e50) / N (teal #1abc9c) proportional flex bars
    • Authors of color: yes (orange #e67e22) / no (dark gray #34495e)
  • Note at bottom: “*2019 me trying to be intentional about what i read”
  • Highlights on hover interaction (see section 3)

2.3.5 Book List (#reading-booklist)

  • Right panel, bottom section
  • Search input (#bl-search): filters by title, author, genre, review text, gender terms, “poc”
  • Scrollable list (260px height) of all 150 books, sorted by rating desc then pages desc
  • Each row: star rating (gold), title, gender badge (F/M/N colored pills), POC badge (orange), genre label (colored)
  • Rows with reviews get .bl-clickable class (underlined title, cursor pointer)
  • Interactive: see section 3 for hover/click behaviors

2.3.6 Emotional Receipt (#reading-receipt)

  • Left side of bottom row
  • Styled as a physical paper receipt (cream background, Courier New monospace font, 1deg rotation)
  • Header: “ANNUAL READING RECEIPT”
  • Table: emotion name and count, sorted by frequency
  • Footer: NET EMOTION (positive/negative percentage), TOTAL PAGES, TOTAL BOOKS
  • Torn edge at bottom (zigzag clip-path)

2.3.7 The Fives (#top-books)

  • Right side of bottom row
  • Lists the top 20 five-star books sorted by page count
  • Each entry: title (gold) + author/genre/pages meta line
  • Books with reviews are clickable (.top-clickable)
  • Click shows the floating review tooltip (see section 3)

3. Interaction Map

3.1 Cork Board Interactions

ElementEventAction
Sticky notes (columns)hoverScale 1.02, straighten to 0deg rotation
Link stickies (WHO IS THIS GUY)hoverScale 1.06, straighten rotation
Link stickies (WHO IS THIS GUY)clickNavigate to external URL (new tab)
QOTD book button (#qotd-book)clickOpens Reading Journal directly for that book (bypasses catalog)
Hidden pin (#shelf-trigger)hoverOpacity rises to 0.6, rotates -8deg, scales 1.15x
Hidden pin (#shelf-trigger)clickOpens Card Catalog modal
”150 books” sticky (#reading-trigger)clickOpens Reading Year modal
Banner kaomojisRotate daily (not interactive)
All kaomojis ([data-kaomoji])Replaced on page load by daily-seeded rotation engine

3.2 Card Catalog Interactions

ElementEventAction
Book spinehoverRises 18px, slight horizontal scale, brightness boost
Book spinemouseenterShows tooltip with title, author, mark count, progress bar, teaser quote
Book spinemousemoveTooltip follows cursor (clamped to viewport)
Book spinemouseleaveHides tooltip
Book spineclickCloses catalog (no scroll restore), waits 200ms, opens journal for that book
Close button (#catalog-close)clickCloses catalog, restores scroll
BackdropclickCloses catalog, restores scroll

3.3 Reading Journal Interactions

ElementEventAction
Back button (#journal-back)clickSaves scroll, closes journal, reopens catalog
Close button (#journal-close)clickSaves scroll, closes journal
BackdropclickSaves scroll, closes journal
Journal pagesscrollUpdates ribbon progress bar (gold fill height = scroll percentage)
Dog-ear button (.je-dogear)hover (entry)Shows gray corner fold on entry’s top-right
Dog-ear button (.je-dogear)clickToggles gold dog-ear. Persists to localStorage. Refreshes TOC to show/hide pin icon
TOC toggle (#toc-toggle)clickToggles TOC panel visibility
TOC item (.toc-item)clickSmooth-scrolls to that passage, hides TOC panel
TOC item (.toc-item)hoverLight gold background highlight

3.4 Reading Year Interactions

ElementEventAction
Wall-mini (book block)hoverEnlarges to 1.3x. If not locked: highlights matching book in book list (gold background), highlights matching genre bar (glow effect), highlights matching gender + POC diversity bars, dims all other wall-minis
Wall-mini (book block)mouseleaveIf not locked: clears all highlights
Wall-mini (book block)clickLocks highlight for 4 seconds. Scrolls book list panel to matching row (smooth scroll within container). Highlight persists during lock period. After 4s, auto-clears
Book list rowhoverGold background on row. Highlights matching wall-mini (enlarges + glow), highlights genre bar, highlights gender + POC bars. Dims non-matching wall-minis
Book list rowmouseleaveClears all highlights
Book list row (with review)clickShows floating review tooltip positioned below the row. Toggle: clicking same book again hides tooltip
Top book (with review)clickShows floating review tooltip positioned below the entry. Toggle: clicking same book again hides tooltip
Book list search (#bl-search)inputFilters book list rows. Searches across: title, author, genre, fiction type, review text, gender terms (“female woman” / “male man” / “nonbinary”), “poc”. Case-insensitive substring match
Review tooltipclick outsideHides tooltip (document-level click listener checks if click target is outside tooltip + clickable rows)
Close button (#reading-close)clickCloses modal, hides review tooltip
BackdropclickCloses modal

3.5 Global Keyboard

KeyContextAction
EscapeJournal openCloses journal (saves scroll)
EscapeReading Year open (journal closed)Hides review tooltip, closes Reading Year
EscapeCatalog open (others closed)Closes catalog

The Escape handler follows a priority chain: journal first, then reading year, then catalog. Only one action fires per keypress.


4. Easter Eggs & Hidden Features

4.1 The Hidden Pin

The primary easter egg. A pushpin emoji (📌) fixed to the bottom-right corner of the viewport at 25% opacity with grayscale filter. It is intentionally near-invisible — the CSS comment reads: “barely visible — only careful eyes find it.” The aria-label is just "?" and the title is empty. Finding and clicking it reveals the entire bookshelf catalog — a substantial hidden experience with dozens of books and hundreds of annotations.

4.2 Daily Kaomoji Rotation Engine

Every [data-kaomoji] span on the page is replaced at load time with a kaomoji drawn from a pool of 245 kaomojis across 12 categories (happy, excited, surprised, angry, sad, cool, fighting, love, shrug, animals, magic, tired, running/chaos). The selection is date-seeded using a Knuth multiplicative hash (seed * 2654435761), ensuring:

  • Same kaomojis for all visitors on the same day worldwide
  • Different kaomojis each day
  • No repeats within a single page load (uses a Set to track used indices)
  • Changes automatically at midnight, no deploy needed

4.3 Dog-Ear Persistence

In the Reading Journal, readers can “dog-ear” individual passages. These persist in localStorage across sessions, creating a personal annotation layer on top of the site owner’s annotations. Dog-eared entries appear with a gold corner fold and are marked with a pin emoji in the TOC.

4.4 Scroll Position Memory

The Reading Journal remembers your scroll position per book (stored in localStorage as js-scroll-{title}). Reopening a book’s journal returns you to where you left off.

4.5 Guilty Gear Stats

One of the “WHO IS THIS GUY” links goes to puddle.farm for Guilty Gear Strive player stats. The sticky itself acknowledges the absurdity: “yes this is a legitimate link section entry.”

4.6 404 Page

The 404 page (/Users/weixiangzhang/Local_Dev/projects/bythewei/src/pages/404.astro) maintains the cork board metaphor with a “fallen sticky” that references a 2:30am Faust match. Three sticky notes explain the error with personality.


5. Accessibility

5.1 ARIA Attributes

  • All three modals have aria-modal="true" and role="dialog" on their backdrop elements
  • The hidden shelf trigger has aria-label="?" (intentionally vague for the easter egg)
  • Dog-ear buttons have aria-label="dog-ear" and title="mark this passage"
  • Journal back button has title="back to catalog"
  • TOC toggle has title="index"
  • QOTD book button has title="see all highlights from this book"

5.2 Keyboard Navigation

  • Escape key: closes modals in priority order (journal > reading year > catalog)
  • Book spines in the catalog are <button> elements (keyboard focusable, activatable with Enter/Space)
  • TOC items are <button> elements
  • Dog-ear buttons are <button> elements
  • Link stickies are <a> elements (natively focusable)
  • The reading trigger and shelf trigger are <button> elements

5.3 Focus Management

  • No explicit focus trapping inside modals — focus is not programmatically moved when modals open or close
  • document.body.style.overflow = 'hidden' prevents background scroll when modals are open
  • No tabindex management or focus restoration on close

5.4 Gaps / Opportunities

  • Modals lack focus trapping (tab can escape behind the modal)
  • No aria-label or aria-labelledby on modal dialogs pointing to their titles
  • No focus is sent to the modal on open or returned to the trigger on close
  • No aria-hidden="true" on background content when modals are open
  • Wall-mini blocks have title attributes for tooltip content but no aria-label
  • The review tooltip is injected into document.body with no ARIA live region announcement
  • Color contrast: some small text (0.6rem, 0.55rem) at low opacity may not meet WCAG AA

5.5 Semantic HTML

  • <blockquote> used correctly for the QOTD passage
  • <button> used for interactive elements (spines, dog-ears, triggers, close buttons)
  • <a> used for external links with rel="noopener"
  • lang="en" set on <html>
  • Viewport meta tag present
  • Open Graph tags for social sharing

6. User Journeys

6.1 Casual Visitor (< 1 minute)

  1. Lands on the page, sees the cork board sprint layout
  2. Reads the banner: “VOXLIGHT — FEB 18 SPRINT”
  3. Scans stat cards (tests passing, RP count, etc.)
  4. Reads the Quote of the Day — a book passage with curly quotes
  5. Skims sticky notes across the 5 sprint columns — gets a sense of what’s being built
  6. Scrolls to bottom row (gaming, reading, runway, agents)
  7. Sees “WHO IS THIS GUY” and clicks a social link (Threads, GitHub, etc.)
  8. Reads the footer, leaves

6.2 Reader / Book Lover (3-10 minutes)

  1. Reads the QOTD passage, intrigued
  2. Clicks the book title under the quote — jumps directly into the Reading Journal
  3. Scrolls through highlighted passages from that book, reading the gold-highlighted first sentences
  4. Dog-ears a few favorite passages (persisted for next visit)
  5. Uses the TOC panel (section sign button) to navigate between passages
  6. Clicks back arrow to discover the full Catalog bookshelf
  7. Browses spines — hovers to see tooltips (title, author, mark count, teaser)
  8. Clicks another book spine to read its journal
  9. Scrolls down and finds the “150 books in one year” sticky
  10. Opens the Reading Year modal
  11. Explores the monthly reading wall — hovers individual blocks to see which book it is and watch the cross-highlighting
  12. Clicks a wall-mini to lock the highlight and auto-scroll the book list
  13. Searches the book list (e.g., “fantasy” or “poc”)
  14. Clicks a reviewed book to read the opinion in the review tooltip
  15. Scrolls to the emotional receipt — reads through the emotion breakdown
  16. Browses the fives section

6.3 Developer / Builder (2-5 minutes)

  1. Immediately recognizes the sprint board / kanban metaphor
  2. Reads the shipped code column to understand what was built
  3. Notes the test counts and audit scores in column 2
  4. Identifies the single gate/blocker (E2E Sync Test) and its pass criteria
  5. Reads the docs & strategy column for architecture insights
  6. Checks the marketing column for go-to-market approach
  7. Clicks the GitHub link (noxwei) to explore repos
  8. Reads the “Agents Used” sticky (Sonnet, Opus 4.6, Claude Code)
  9. May discover the hidden pin and explore the catalog as a technical curiosity
  10. Notes the tech stack from the stats (SyncEngine lines, Shortcuts spec)
  11. Checks the blog post link via simplephilosopher.com

6.4 Return Visitor

  1. Sees new daily kaomojis and a new QOTD (changes at midnight)
  2. Opens journal for a previously-read book — scroll position restored
  3. Dog-eared passages are still marked from previous visit
  4. Sprint data reflects the latest update (when sprint.json is changed)

Data Architecture

Data Files

FilePathPurposeLoad Strategy
sprint.json/src/data/sprint.jsonSprint board content (columns, stickies, stats, bottom row, footer)Imported at build time (Astro frontmatter)
bookmarks.clean.json/src/data/bookmarks.clean.jsonBook highlights/annotations from Apple BooksFetched at runtime via fetch('/data/bookmarks.clean.json')
reading-log.json/src/data/reading-log.json150-book reading log (2019-2020) with ratings, genres, emotions, reviewsFetched lazily on first open of Reading Year modal
kaomojis.ts/src/data/kaomojis.ts245 kaomojis in 12 categoriesImported at build time, passed to client via define:vars

Local Storage Keys

Key PatternPurpose
de-{title20}-{index}Dog-ear state for individual journal passages
js-scroll-{title20}Scroll position in journal for a specific book

File Map

/Users/weixiangzhang/Local_Dev/projects/bythewei/src/
  layouts/
    Layout.astro          -- base HTML shell, fonts, CSS variables, cork texture
  pages/
    index.astro           -- entire site: template + 3 modals + JS + CSS (~2490 lines)
    404.astro             -- themed 404 page
  data/
    sprint.json           -- sprint board content
    bookmarks.clean.json  -- book highlights (runtime fetch)
    bookmarks.json        -- raw bookmarks (not used by index)
    reading-log.json      -- 150-book reading year data
    kaomojis.ts           -- 245 kaomojis for daily rotation