Enrich catalogue detail pages (games, books, movies/series, anime) - #141
Merged
Conversation
Add franchise name, age ratings, trailer, multiplayer modes and vote counts to the game detail page, make the IGDB rating clickable, and animate the collapsible "Histoire" section. The trailer now plays as an extra slide inside the existing screenshot lightbox rather than a separate modal, fixing two related bugs along the way: the play button's fragile centering (inset-0 + margin:auto silently breaks without inset-0) and the video being unclickable (a non-positioned element always paints under its positioned siblings, so the transparent lightbox backdrop button was swallowing clicks meant for the player). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add ISBN, series, language, edition count, first sentence, a
"read online" link (public Internet Archive scans only) and
Goodreads/LibraryThing/Amazon links to the book detail page, and make
the Open Library rating clickable.
These are all edition-scoped fields, but Open Library's /search.json
work document aggregates them across every edition/translation ever
catalogued with no way to tell which array entry belongs to which
edition — picking e.g. language[0] surfaced an unrelated translation's
language at random. Fixed by having /search.json nest one concrete,
language-matched edition via `lang=`+`editions.*` (native to the API,
no extra request), then following up with a single /books/{OLID}.json
call for the fields that nested doc doesn't carry (series, first
sentence, cross-reference ids, an edition-specific description
override). The book's own page and the rating both link to that
edition's /books/ page instead of the abstract /works/ page.
`lang` now threads from the client's active UI locale through search
and the detail page, so search results and the description prefer an
edition in the reader's own language when Open Library has one.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds native rating (with link), tagline, director/creator, trailer and official content rating to the media detail page, plumbing `lang` through search/detail/extras to match the books/games locale work. Also fixes a real bug this surfaced: the media detail page serves from the DB cache once an item is referenced, so a cached English title/overview stayed English forever even when browsing in French. Introduces MediaItemTranslation, a minimal per-locale cache (title/overview/genres) layered on the base MediaItem row and refreshed on the same sync cycle — kept consistent between the library list and the detail page. The admin cache page now shows how many locales are cached per item.
Adds Japanese voice actor pairing (replacing the character's plain MAIN/SUPPORTING role tag), credited director(s) via staff, trailer, main studio(s), release format/season, related titles (sequels/prequels, filtered to anime-type nodes), external links and non-spoiler tags — mirroring the TMDB extras added earlier this session. Also points the AniList rating link at the source's own siteUrl instead of a hand-built URL. Also guards MediaItemService.translationFor() against AniList: it has no localization support, so a "French" fetch would just duplicate the English base row — skip it instead of wasting a live call and a DB row.
AniList's schema doesn't accept `sort` on Media.tags (confirmed against the live API) — the getExtras call for anime was failing outright. Fetch `rank` instead and sort client-side before filtering out spoiler tags.
Distribution still showed the character's name with the voice actor tucked into the role subtext — backwards from the intent (and from TMDB's actor→character pairing). Swap name/photo to the Japanese voice actor when one is credited, character name as the role underneath; falls back to the character alone otherwise.
Distribution now shows both faces on anime cards — the Japanese voice actor on the left, the character on the right — instead of just one photo, and clicking a voice actor opens the same cast modal TMDB actors already get: bio, birth year/hometown, and a carousel of the anime they've voiced characters in (AniList's `characterMedia`, filtered to anime-type credits). AniList bios use a light markdown dialect, so strip it before display instead of showing raw `**bold**`/`[link](url)` syntax.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a batch of provider fields that were fetched but unused (or not fetched at all) across every catalogue detail page, following a cross-provider inventory. One commit per domain:
/search.json's aggregated-across-editions work document — now resolved vialang=+nestededitions.*, plus a per-edition/books/{OLID}.jsonfollow-up call. Links point at the concrete edition, not the abstract work page.MediaItemTranslation, a minimal per-locale cache (title/overview/genres) so a French user no longer sees a stale English title/overview on an already-cached title — kept in sync with the library list and refreshed on the same cycle as the rest of the cached item.siteUrlfor the rating link. Also guards the new translation cache against AniList, which has no localization support.Test plan
pnpm build:packagepnpm --filter @loomkeep/api exec tsc --noEmitpnpm --filter @loomkeep/web check(0 errors)getExtras, the translation cache, and the AniListgetPersonstaff lookuptags(sort:)400 before merge)🤖 Generated with Claude Code