Skip to content

feat: endless deck — bigger pool, varied sorting & on-demand top-up - #33

Merged
valeboth merged 1 commit into
mainfrom
feat/deck-topup
Aug 28, 2026
Merged

valeboth merged 1 commit into
mainfrom
feat/deck-topup

Conversation

@valeboth

@valeboth valeboth commented Aug 28, 2026 •

Copy link
Copy Markdown
Owner

Problem

The deck was a generate-once, finite pool of popular titles. A user could swipe through it in a single sitting and hit "That's the whole deck 🎉" with no way to get more — and because both taste slices returned the same popular films, the unique pool was small.

What changed

Three things, all bounded to stay on the Cloudflare free tier:

  1. Bigger initial pool — common-ground slice 1→2 pages; each no-seed genre slice now uses a different sort so the pool spans popular / acclaimed / recent instead of all-popular.
  2. Varied sorting + deeper reads — discoverTitles gains startPage and sortBy options (no behaviour change at defaults).
  3. On-demand top-up — new GET /api/rooms/:id/deck/more extends the same shared pool (both users converge → matches still work), deduped and capped at MAX_DECK = 300. The frontend prefetches more once ≤5 cards remain, so swiping feels endless; when the cap is hit it falls back to the existing empty-deck message.

Free-tier safety

  • MAX_DECK = 300 caps TMDb calls, KV writes and the size of the D1 rooms.deck row. A full room ≈ 15 TMDb pages (cached), ~7 KV writes, a ~90KB deck-cards value — the tightest free-tier limit (KV writes, 1k/day) stays far off.
  • Top-up reads only 2 pages, served from the 24h KV cache after the first fetch.
  • The page cursor is derived from pool size (topupCursor) so we never re-fetch pages we already have.
  • No schema change, no new bindings.

Tests

  • topupCursor is pure and unit-tested (page advance + sort rotation).
  • typecheck, lint, vitest (6/6) and wrangler deploy --dry-run all pass.

The deck was a finite, generate-once pool of popular titles: users could
swipe through it in one sitting and hit "that's the whole deck" with no way
to get more. Three changes, all bounded to stay on the Cloudflare free tier:

- Bigger initial pool: common-ground slice 1→2 pages; each no-seed genre
  slice uses a different sort (popularity / rating / recency) for variety.
- discoverTitles gains startPage + sortBy so we can read deeper pages and
  diversify without new endpoints.
- On-demand top-up: GET /api/rooms/:id/deck/more extends the SAME shared
  pool (both users converge → matches still work), capped at MAX_DECK=120.
  Frontend prefetches more once ≤5 cards remain, so the deck feels endless.

Free-tier safety: MAX_DECK caps TMDb calls, KV writes and the D1 deck row;
top-up reads 2 cached pages; the page cursor is derived from pool size so we
never re-fetch. topupCursor is pure + unit-tested.
@valeboth
valeboth merged commit b352715 into main Aug 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant