A running tally of every album, film, and series logged here — how often each feeling comes up, which genres keep pulling me back, and how this site got built along the way.
TRACK 01 — SUMMARY TRACK 02 — MOOD MAP TRACK 03 — BUILD
Every album, film, and series gets logged here — what it was, why today, and up to three feelings that came with it.
This site's own history, pulled straight from git — every change, grouped by the day it happened.
Why this log exists, and what the entries add up to when you read them all at once.
One suggestion per kind of thing, picked from the genre you've tagged most often in that category — and filtered to leave out anything already in the log.
This log is also a build log. Every change to the site is a commit, and those commits get read straight out of git each time it deploys — so the numbers below can't drift from what actually shipped.
Each commit is bucketed by what it touched. Many land in more than one.
Supabase reads and writes, auth, and the lookup APIs.
Layout, components, tabs, and everything you actually see.
The entries table, its columns, and moving old data in.
Astro, TypeScript, the build pipeline, and project structure.
Keeping the spec honest about what the thing actually does.
Getting it online: Cloudflare Pages, GitHub, deploy scripts.
Colour, type, spacing — how the whole thing feels.
Versions read from package.json at build time.
The three most recent working days. Full history lives on the Dev Log tab.
439d0f2 Add a bulk importer for pasted lists a822178 Loosen Apple Music matching to accept romanized artist names c3fbe81 Stop storing wrong Apple Music links, and widen the ISBN lookup 19c34e7 Render notes as Markdown, link music to Apple Music, and support phone capture 89f84b0 Add an About tab, auto-fetch covers, and suggest genres up front 18693b8 Add entry editing, pagination, and real cover artwork a549e06 Repaint in pastel, rename Overview to Home, and surface the build story 774a911 Give each tab its own hero copy 41f12e8 Scroll to top when switching tabs 9bad919 Add a Dev Log tab and regroup the page into three tabs 34d017e Point deploys at the moodlogremi.pages.dev project 50f41d2 Add deploy script and document the Astro/Cloudflare setup How this site got built, day by day — read straight from the repository's own history at build time.
439d0f2 Add a bulk importer for pasted lists Paste one item per line — title, title | creator, or title | creator | date — pick a type, and each line runs through the same lookup the form uses. Results are shown with tick boxes for approval before anything is written: a wrong match buried in a batch of thirty is far harder to notice afterwards than before. Unresolved lines are listed with the reason rather than dropped, and feelings are left empty on purpose — no lookup can supply them, and guessing would defeat the point of the log. Built to carry an Instagram export into the log, but useful for any list.
a822178 Loosen Apple Music matching to accept romanized artist names Requiring the artist to agree as well as the title looked like the safe reading, but it threw away most correct matches: iTunes romanizes names, so 落日飛車 comes back as "Sunset Rollercoaster" and 宋冬野 as "Song Dongye". Seven of eight albums found no link because of it. An exact title match now stands on its own; a merely partial one still needs the artist to back it up, which is what actually stopped the "愛是唯一" → "I Swear" mismatch. If nothing matches, title and artist are retried swapped — entering an album under the artist's name is an easy slip and the swap recovers it.
c3fbe81 Stop storing wrong Apple Music links, and widen the ISBN lookup iTunes ranks loosely — searching "愛是唯一" returns Sandy Lam's "I Swear" first, because one of its tracks carries that name, and taking results[0] on faith had already written that wrong link to a real entry. Candidates are now checked against the entry's title and artist, and an unconvincing search stores nothing: a missing link is recoverable, a wrong one silently isn't. ISBN lookup now tries three shapes — Google Books' isbn: index, Google Books' plain search, then Open Library — and sends country=TW, which Google Books requires from some regions or it errors rather than returning an empty list. Open Library genuinely has no record of the reported ISBN (numFound: 0), and Taiwanese titles are often missing from both indexes, so the failure message now names what was tried and points at a title search instead of implying the input was wrong.
19c34e7 Render notes as Markdown, link music to Apple Music, and support phone capture - Notes accept Markdown, rendered by a small in-repo renderer rather than a dependency. Safety comes from ordering: the source is escaped first and only then re-marked-up, so a note can't inject HTML, and link hrefs are restricted to http(s). Checked against <script>, <img onerror>, and javascript: links - Notes over 100 characters collapse to a plain-text preview with Read more; the full Markdown is parsed on demand rather than for every card up front - Saving a vinyl entry now looks up its Apple Music page when it doesn't have one, so albums logged from Spotify, YouTube, or by hand are still one tap from playing. The backfill button fills links as well as artwork - ISBNs are detected and queried exactly, via Google Books then Open Library — more reliable than a title search, and easy to copy off a bookshop page whose link can't be read - Added a web manifest for Add to Home Screen, and URL prefill (?add=1&type=&title=&creator=¬e=) so a phone shortcut can hand data over without holding credentials — it opens a URL in the already-signed-in browser Fixed while testing: blockquotes never rendered, because escaping runs first and turns "> " into "> " before the block rule sees it.
a1d6fc6 Link entries out to their source, add All filters, and improve book lookup - Every lookup now also returns where to go to play/read/watch the thing, stored in a new source_url column. Timeline cards get a link named after the destination — "Apple Music ↗" on an album, "IMDb ↗" on a film. Pasted links are kept as-is. Probed like cover_url, so it degrades until the column exists - Books try Google Books before Open Library: it indexes Chinese-language editions far better. A bare ISBN is detected and queried as isbn: - books.com.tw and the other online bookshops block cross-origin reads (403 even server-side), so those links are detected and answered with a nudge to type the title or ISBN, rather than a generic "not recognized" - Both filter rows lead with an explicit All chip — "select nothing to see everything" was never discoverable - Dropped the ↺ marker on remembered genres; their position already says it
28db8b3 Collapse repeat logs in the timeline, and tidy the filter and utility rows Logging the same work again now folds into one timeline card showing ×N and the last date, carrying the most recent log's mood. Identity is title + creator + media type, case-insensitive — title alone would conflate an anime with the book behind it. Two deliberate limits on that: - The database still stores every log. This only folds them for display, so the history behind a "×3" survives and the choice stays reversible - Deduping is timeline-only. The Mood Map still plots every log so repeat listens keep their own shape, and Summary still counts logs. Remove on a folded card drops only the latest and says so, rather than silently taking three records with one click UI: backup/maintenance actions move behind a "Manage this log" disclosure instead of reading as developer tooling; the genre filter collapses to the 8 most-used with a "+ N more" toggle (active filters stay visible regardless); and entries without notes render nothing instead of a grey "(no notes)". Backend: split renderAll into renderAll/renderFiltered so a filter click stops rebuilding the stats and the About copy, and run the two schema probes concurrently instead of sequentially.
6e184c4 Drop the Home tab, rework Summary, and add recommendations - The Home tab is gone; the MOOD LOG wordmark navigates there instead, the way a site logo usually does. Nav is now Log · Dev Log · About - Summary reworked: one large total, the date range collapsed to a single line with a day count, per-type counts inline as colored dots, and feelings/genres side by side. Previously six same-sized tiles with dates taking two of them - New "You might like" section: one suggestion per media type, drawn from the genres that type is tagged with and filtered against what's already logged Three things the obvious implementation got wrong, found while testing: - iTunes only matches titles, so searching it for "Sci-Fi" returns nothing. Films now come from Wikidata, ranked by sitelink count - AniList keeps "Shounen"/"Isekai" as tags, not genres, and querying them as a genre returns an empty list rather than an error. The code now checks GenreCollection and picks the right field, with an alias map for romanization - With few entries every genre ties at one, so the "top" genre is arbitrary and was often a word the source didn't know. Candidates are now tried in rank order until one answers
665cfd7 Add a Book type, editable About copy, and genre memory - Book joins Vinyl/Movie/Anime: Book/Author fields, reading contexts, and lookups through Open Library (keyless, CORS-open, good on translations). Goodreads links can't be read cross-origin, so the title is recovered from the URL slug and searched instead - About prose now lives in a site_settings key/value table and is editable in place by the owner. Probed like cover_url, so it falls back to built-in copy when the table doesn't exist yet - Genre chips remember what each media type has actually been tagged with, ordered most-used first (↺) ahead of the presets — custom genres stop needing to be retyped - Replaced the capybara with a cozy window scene in the reference style Needs a schema migration (see SPEC): cover_url, a widened media_type check for 'book', and the site_settings table.
a6eb826 Paginate the mood map, visualize dev stats, and fix genre language and covers - Mood Map legend paginates at 10. The radar still draws every visible entry, and clicking a polygon jumps the legend to the page holding it, so a click never lands on something off-page - Dev Log gains two wordless summaries: a proportional bar of what the work has been made of, and a per-day activity strip. No figures on purpose - About drops the generated data portrait for a capybara in a hot spring - Genre language: iTunes answers in the storefront's language, so a US lookup now backfills the genre when the first answer is CJK, and Latin-script labels win over CJK ones when both exist ("Alternative", not "另類音樂") - Covers for film and anime: Wikidata's P18 is often empty, so films fall through to Wikipedia's summary endpoint and anime to an AniList search — both keyed on Wikidata's English label, since neither source matches a Chinese title
89f84b0 Add an About tab, auto-fetch covers, and suggest genres up front - New About tab. The prose is fixed, but the "portrait in data" beside it is generated from the log itself — counts, the feelings that recur, what gets returned to — so it stays true as entries accumulate rather than going stale - Covers are now looked up automatically on save when the entry doesn't already have one, so "Fetch missing covers" is only for backfilling old entries - Genres the lookup suggests are pinned ahead of the presets and marked, so the system's guess is what you see first - Removed "Clear all entries" (and the deleteMany call that only served it) Backend tidy-up while in here: fetchEntries now sorts newest-first in the database instead of the client re-sorting in three places, and it propagates errors so a failed load says so rather than looking like an empty log.
18693b8 Add entry editing, pagination, and real cover artwork Editing: each timeline card gets an Edit button for the owner that loads the entry back into the add form, swaps the submit label, and shows a cancel banner. Saving updates in place. An edit survives routine auth-token refreshes — only an actual loss of owner rights discards it. Pagination: 10 per page on both the Timeline (re-rendered) and the Dev Log (hidden/shown in place, since Astro renders it statically; day headings collapse when a page leaves them empty). The pager hides itself below one page. Covers: every lookup source now also returns artwork — iTunes (upscaled from the 100px thumb Apple returns), Spotify/YouTube thumbnails, Wikidata P18, AniList coverImage. Entries fall back to the generated SVG when there's no image or it fails to load. A "Fetch missing covers" utility backfills older entries. The cover_url column is probed once at boot and omitted from writes when absent, so this works against a database that hasn't run the ALTER TABLE yet. Also wired up astro check (0 errors) and pinned down a Tailwind/Vite types skew.
a549e06 Repaint in pastel, rename Overview to Home, and surface the build story - New light pastel palette across tokens, emotions, genre cycle, and type accents, taken from the reference player artwork: soft peach/pink/lavender wash, translucent white cards, muted purple ink - Each tab gets its own illustration instead of sharing the record: a player window (Home), an open journal (Log), a code window (Dev Log). The record only spun on one tab's worth of meaning anyway - Dropped the SIDE A / SIDE B fineprint from Log and Dev Log - Overview renamed Home; hash is now #home - devlog.ts now classifies each commit into work areas (frontend, design, backend & data, database, framework & build, deploy & infra, docs) and reads the stack's versions out of package.json. Home gains a "How it was built" section showing the breakdown, the stack, and recent changes; Dev Log tags each commit with its areas - A tracked pre-push hook redeploys on every push so the live Dev Log always matches GitHub; failures are swallowed so they can't block a push. `npm run ship` does the same explicitly
774a911 Give each tab its own hero copy The banner was one static block shared by all three tabs, so its text didn't describe whatever was actually showing below it. Hero now renders three variants (eyebrow/title/lede/fineprint), toggled by the same showTab() that already switches [data-panel] — Overview talks about the aggregate stats and mood map, Log about adding/browsing entries, Dev Log about the build history.
41f12e8 Scroll to top when switching tabs Keeps the new tab starting at its own beginning instead of inheriting the previous tab's scroll position. Honours prefers-reduced-motion.
9bad919 Add a Dev Log tab and regroup the page into three tabs The nav is now a tab switcher rather than anchor links, with the active tab mirrored to the URL hash so tabs can be linked directly. - Overview holds Summary + Mood Map; Log holds Add Entry + Timeline (the backup/utility row moves here, next to the entries it acts on); Dev Log is new - Dev Log reads `git log` at build time via src/lib/devlog.ts and groups commits by day. Chosen over the GitHub API so it needs no rate limit budget and keeps working while the repo is private; it refreshes on rebuild - "Locate on map" now switches to the Overview tab before scrolling
34d017e Point deploys at the moodlogremi.pages.dev project 50f41d2 Add deploy script and document the Astro/Cloudflare setup 9d141f0 Rebuild as an Astro + Tailwind project Replaces the single hand-written index.html with a real build: Astro for the static shell, Tailwind v4 for styling, TypeScript for the client logic. Output is still a static site — no adapter, no server. - src/components/* hold the page shell; all dynamic rendering stays client-side in src/lib/app.ts, which fills the sections from Supabase - src/lib splits the old monolith into config (media types, emotions, palette), supabase (typed CRUD), art (cover art + radar), parse (link/title lookup) - Design tokens moved into Tailwind's @theme, so colors and fonts are utilities; only the paper grain, record spin, and timeline rail stay as custom CSS - Behaviour and the Supabase schema are unchanged Node was upgraded to 26 (Homebrew) since Astro's Vite needs >=20.12; the old system Node 20.10 at /usr/local/bin is untouched and still resolvable.
0ac4f3a Fix stale note about the parse box being type-gated bef6b33 Update spec for movie/anime parsing and title search 4d789f3 Parse movie and anime sources, and accept a plain title anywhere The parse box is now shown for every media type and takes either a link or a title to search for. - IMDb links resolve through Wikidata (keyless, CORS-open): localized title, director, and genres normalized against this app's presets - MyAnimeList and AniList links resolve through the AniList GraphQL API - Typing a name searches Apple Music (vinyl), Wikidata (movie), or AniList with a Wikidata fallback (anime) — Wikidata is what makes Chinese titles work, since AniList only indexes romaji/English/Japanese - Streaming hosts (Bahamut, Netflix, Bilibili, …) forbid cross-origin reads, so their pages cannot be inspected client-side at all; those links now say so and point at the title search instead - Enter in the parse box triggers a parse
6271811 Update spec for single-page lifelog architecture and Supabase backend 1bde107 Restructure as a single lifelog page with a type selector Vinyl/Movies/Anime are no longer separate tabbed pages. The lifelog rollup is now the only header: one hero, then Summary, Add Entry, Timeline, Mood Map as sections of one page, with nav links as anchors. - One add form; a Type chip row swaps field labels, placeholders, context options, genre presets, submit label, and shows the link parser for Vinyl only - Timeline and Mood Map cover every type at once, filterable by type and by genre (the genre list narrows to whatever the type filter leaves in scope) - Entries normalize to {mediaType,title,creator,...}, dropping the per-type titleKey/creatorKey indirection; DB schema unchanged - Migration is one button covering all three legacy stores - Link parser tolerates messy pasted URLs and supports Spotify - Added cover-art shapes for film/anime genres
93f4623 Add migration for movie/anime tabs, support Spotify links in parser - migrateLocalLegacyData is now config-driven (per-media legacy storage keys) and checks both Claude storage and localStorage, skipping entries already in the cloud - Parser recognizes Spotify links via oEmbed (title only; Spotify does not expose artist or genre)
33c5088 Add Mood Log app (Vinyl/Movies/Anime/Lifelog, Supabase-backed public site)