Repository navigation
feat(catalog): turn /shows and /movies into carousel landings with list pages - #45
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y states Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
An encoded slug such as /shows/top%2Drated passed the proxy but reached [id], a soft 404. Also renames lists to listMediaType. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
listPath and listPageHref take the CatalogList, so a slug can no longer travel apart from its media type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All ten lists held the same text, so the field carried nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…card mapper Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…list pages Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch was successfully deployed
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.
What
/showsand/moviesare no longer one paged grid of 20 popular titles. Each one is now five rows that scroll sideways (carousels) of TMDB lists. Each row has a See all link to its own paged list page, for example/shows/top-ratedor/movies/now-playing. Nothing is stored and the schema does not change.Why
This implements spec 0021, Home carousels (scope feature 24). Visitors can now see several kinds of lists at once (trending, popular, airing or in cinemas, top rated) instead of paging through one list. Every card still shows and changes the signed in user's tracking state, the same way the grid does. Old
?page=Nbookmarks keep working.Changes
TMDB reads
lib/tmdb/lists.tswithfetchTvListandfetchMovieList. They cover trending (week), airing today, on the air, now playing, upcoming and top rated. Only the dated lists send a place:timezone=Europe/Warsawfor TV andregion=PLfor movies. Results that TMDB flagsadultare dropped, because these endpoints take noinclude_adult(AC-8).getTvListandgetMovieListinreads.tsareuse cachewrappers. They usecacheLife("hours")on success and the existing failure profile on failure. Popular still uses the existing discover reads, so it shares cache entries with the sitemap.List registry and dispatcher
lib/catalog/lists.ts: a pure registry of the ten lists (slug, row title, h1, note, page noun, paths,isCatalogListSlug). It has noserver-only, so the proxy and the sitemap can import it.lib/catalog-list-read.ts:readCatalogList(list, page). This is the one place a slug turns into a TMDB call. A row and page 1 of its list page make the same cached call, so opening See all costs no extra request (AC-3).UI
CarouselRow(server) renders a labelled<section>with a header (h2, See all, arrows). Its cards stream in their own Suspense boundary, with 12 card skeletons as the fallback. If one row fails or comes back empty, only that row shows a compact error or empty state (AC-11, AC-12).CarouselScroller(client) is a focusable scroll region with scroll snap. Frommdup it adds back and forward buttons that scroll 90% of the visible width. It respects reduced motion, and each button is disabled at its end of the row.CatalogListPageis the shared paged list page: back link, h1, source note, grid and pagination, plus the "no such page", error and empty panels. The show and movie card renderers were pulled out intolist-cards.tsx, and rows and list pages both use them.PosterCardgets an optionalsizesprop, so carousel cards (140px, 180px frommd) request the right image width./showcaseshows the carousel row and its loading, error and empty states.Routing, SEO
app/shows/{slug}andapp/movies/{slug}, each withgenerateMetadatabuilt from the registry./shows/upcomingor/shows/Popular(AC-13).next.config.tsadds permanent (308) redirects:/shows?page=Ngoes to/shows/popular?page=N, and the same for movies (AC-14).How to test / verify
pnpm typecheck,pnpm lintandpnpm test. The new and rewritten suites arelib/tmdb/lists.test.ts,lib/catalog/lists.test.ts,lib/catalog-list-read.test.ts,app/catalog-lists.test.ts,app/movies/request-scope.test.ts, thecomponents/catalog/*tests,proxy.test.ts,next.config.test.tsandapp/sitemap.test.ts.TMDB_READ_ACCESS_TOKEN= pnpm build. It should pass, because rows read TMDB only at request time (AC-7)./showsand/moviesat 1280px. You should see five rows each, in spec order. Press the arrows (back starts disabled), then try 375px: there should be no arrows and no sideways page scroll.?page=abcand?page=600; both should show "That page doesn't exist".curl -sI "localhost:3000/shows?page=3"should answer308withlocation: /shows/popular?page=3.curl -s -o /dev/null -w "%{http_code}" localhost:3000/shows/upcomingshould answer404.pnpm dev:dockerasuser-a@example.test, track a show from a row. Its badge should match its library page.Risk & rollout
Low risk, no migrations, no flags. These are public catalog pages only, with no new user data reads. The TMDB list reads take no cookie, header or search param, and the request scope test covers the landings and list pages (AC-17). The
?pageredirect is a 308 on purpose, so browsers cache it for good;/shows?page=Nhas no future meaning. Rolling back means reverting the PR, but browsers that already cached the 308 keep sending?pagebookmarks to/…/popular, which still works.Notes for reviewers
verify.mdare still unticked: the Warsaw midnight check for Airing today, and the signed out bookmarkreturnPathround trip. Every other step is ticked./check reviewhas run for this branch yet. There is no review indocs/reviews/.PLregion andEurope/Warsawtimezone are a deliberate choice. Following each visitor's region is recorded as deferred in the scope.🤖 Generated with Claude Code