Skip to content

feat(catalog): page every title grid 24 at a time so rows stay full - #47

Merged
kris1027 merged 14 commits into
mainfrom
feat/full-grid-rows
Oct 13, 2026
Merged

kris1027 merged 14 commits into
mainfrom
feat/full-grid-rows

Conversation

@kris1027

Copy link
Copy Markdown
Owner

What

Every paged title grid now shows 24 titles a page instead of 20, and the catalog grid steps 2, 3, 4 and 6 columns (the 5 column step is gone). A full page now fills every row at every width.

Why

With 20 titles a page and a 6 column grid, a page at 1280px and wider ended 4 cards short, and pages at 3 and 5 columns had ragged last rows too. 24 divides evenly by 2, 3, 4 and 6. This amends spec 0022 (AC-1, AC-2, AC-4, AC-6, plus new AC-21 and AC-22), decided in the 2026-10-13 grilling session. The plan is in prompts/full-grid-rows.md, and the reasoning is in docs/specs/0022-card-size-title-pages/rationale.md.

Changes

  • A new 24 title window over TMDB's 20 result pages (lib/catalog/grid-page.ts, pure, no server-only). Page p shows TMDB results (p - 1) × 24 + 1 to p × 24. These always sit on two TMDB pages, which are read in parallel through the existing cached reads, so neighbouring pages share cache entries. A TMDB page past 500 is never requested. The last page is ceil(min(total_results, min(total_pages, 500) × 20) / 24), so a 10,000 result list ends at page 417 with 16 titles. If either read fails, the whole page fails and shows the usual error panel with Retry.
  • Repeated titles at a TMDB page edge. TMDB sometimes returns the same title at the end of one page and the start of the next. Popular movies does this today (id 1284046), which left page 1 at 23 cards. The window keeps that title once and fills the gap from results already read past the window. Each TMDB page is cut by its own positions, so the next page never shifts.
  • See all list pages read through the new readCatalogGridPage and readTaggedCatalogGridPage (lib/catalog-list-read.ts). generateMetadata uses the same read, so canonicals and noindex follow the new page count at no extra TMDB cost. The home rows still read TMDB page 1 through readCatalogList, unchanged.
  • /search browse, search and discover modes read through readGridPage. Filtered search (a query plus genre or rating) is unchanged and stays cursor based, with its 20 match scan target.
  • Library tabs page by 24: LIBRARY_PAGE_SIZE = GRID_PAGE_SIZE.
  • Grid and skeletons. The catalog columns become grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-6, with new sizes worked out by the AC-4 rule. Both page skeletons show GRID_PAGE_SIZE cards, and the LibrarySkeleton row visibility follows the new steps. The season grid (wide) is unchanged.
  • Pages past the end. Callers now use the grid's own totalPages, which is already capped, so lastReachablePage is no longer applied on top of it in the list page and search results.
  • Docs. Spec 0022 is amended, specs 0008, 0020 and 0021 get one line amendment notes, and components/AGENTS.md describes the new column steps.

How to test / verify

  • Suggested checks: pnpm typecheck, pnpm lint, pnpm test, pnpm build. The new lib/catalog/grid-page.test.ts covers the window at several pages, dropping TMDB page 501, consecutive pages with no gap or repeat, the repeated title case, a short TMDB page, and the last page maths. poster-grid.test.tsx now checks that 24 divides every column step.
  • Run pnpm dev:docker and open /movies/popular at 1440px: you should see 4 full rows of 6. At 1100px you should see 6 rows of 4, at 700px 8 rows of 3, and at 375px 12 rows of 2, with no gaps.
  • Note the last card on page 1, then open page 2: its first card should be the next title, and the last page in the pagination should match the count.
  • /movies/popular?page=417 should show up to 16 cards, and ?page=418 should show "That page doesn't exist".
  • /search?type=tv and /search?type=movie&q=star should show 24 cards in full rows, and pages 2 and 3 should work.
  • /search?type=movie&q=star&rating=7 should behave as before: a variable card count and the "More results" cursor.
  • Signed in with 25 or more planned movies, /watchlist?type=movie should show 24 cards on page 1 and the rest on page 2.
  • The /shows and /movies landing rows and a show's season grid should look unchanged.

Risk & rollout

Low risk: no migrations, no flags, no schema or RLS change. Only public catalog data passes through the new window, and each TMDB read keeps its existing cache key. Two things change on purpose. A catalog or search page now costs two TMDB reads instead of one, and an old ?page=N link now points at different titles. Old links are not redirected; a link past the new last page shows the existing "That page doesn't exist" panel.

Notes for reviewers

  • The window maths in combineGridPage is where an off by one would hide, since a skipped or repeated title looks fine on screen. The tests check result positions rather than counts for that reason.
  • Short rows are still accepted on the last page of a list, a filtered search page, a library page after a card is removed in place, a page where TMDB repeated a title and nothing was read past the window to fill the gap, and the season grid (AC-22).
  • TMDB_PAGE_SIZE moved to lib/catalog/grid-page.ts. lib/search/constants.ts re-exports it, so the filtered search scan is untouched.

🤖 Generated with Claude Code

kris1027 and others added 8 commits October 13, 2026 17:20
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>
…e edge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kris1027 kris1027 added docs Documentation additions and updates improvement Enhancements to existing functionality test Automated tests and test infrastructure ui Layouts, styling, and shared interface components labels Oct 13, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in BeStats Oct 13, 2026
@kris1027 kris1027 self-assigned this Oct 13, 2026
@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
bestats Ready Ready Preview Oct 13, 2026 3:51pm UTC

kris1027 and others added 6 commits October 13, 2026 17:47
…the window's two pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…trust its capped count

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>
…ast the end

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…8 and 0009 verify steps

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kris1027
kris1027 merged commit 9780560 into main Oct 13, 2026
4 checks passed
@kris1027
kris1027 deleted the feat/full-grid-rows branch October 13, 2026 15:54
@github-project-automation github-project-automation Bot moved this from In review to Done in BeStats Oct 13, 2026

This branch was successfully deployed

1 active deployment
Preview — fbc04435 Deployed Oct 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation additions and updates improvement Enhancements to existing functionality test Automated tests and test infrastructure ui Layouts, styling, and shared interface components

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant