Discover refresh and smaller batches
The control placement described below is superseded by the owner's floating-control revision. Batch size and request-safety behavior remain in place.
User behavior
Clean Discover requests 12 cards at a time instead of 24. The existing sentinel prefetches within 800px of the viewport; this is a network batch size, not a cap on visible cards and not an automatic reshuffle after every twelve cards. Search, tag-filtered and other sorts retain 24-card requests.
A sticky Refresh control stays below the application header on desktop and mobile. It advances the current recommendation stream and replaces the visible batch only after new eligible cards arrive. It keeps the old cards during a request, on failure, and when no unseen cards arrive. Empty batches report their state rather than erasing the feed or retrying indefinitely. Exhausted/expired streams can start a fresh request; client-side delivered IDs still suppress repeats during the same mounted visit. Reloading the application starts a new client history. The finite catalog still limits how many unseen stories exist.
Ordinary pagination preserves reading position. A successful explicit refresh moves to the start of the recommendation grid, below the header, and restores button focus. It does not jump to the hero or reset taste, interests, Library, content settings or account state. Each card keeps its served page's absolute position and attribution. Loading more and refreshing cannot race each other.
Ranking and interests: unchanged by this release
The active recommendation profile already uses favorites, ratings, Library activity/play depth, followed creators, related tags and collaborative signals. This UI change does not demonstrate improved ranking quality or make every PostHog event available as a clean training label.
The existing optional interest chooser has Skip, later editing/resetting, localized labels, eligible-supply checks and preference handoff tests. It remains disabled. interestOnboardingEnabled() currently depends on the richer personalization master flag. With that flag off, loadPreferenceState() also returns empty state and loadPersonalizationContext() returns null. Turning on only the UI flag therefore cannot make choices affect the feed. Turning on the richer model simply to expose the chooser would conflate two experiments.
The next isolated ranking change should use explicit interests under its own cohort gate, with the same mapping for catalog coverage, candidate retrieval and scoring. Both cursor serving and the baseline admission fallback must apply it; preference revisions must invalidate cached recommendations. Start with the signed-in private cohort, verify each supported language's eligible supply, and keep rich embedding retrieval disabled. Guest rollout additionally needs shared cookie identity, cache partitioning and verified handoff semantics. No new paid service is a prerequisite.
Existing audit-based categories are relationships/romance, fandom, idols, simulation, fantasy/adventure and mystery. Do not fabricate inventory or infer a fixed personality from a single click. Treat choices as soft positive evidence; skipping or leaving a choice unselected is not negative feedback.
Verification
- 69 focused client tests pass, including threshold scrolling, document/element refresh destinations, header overlap, concurrent operations, failed retries, expiry recovery, attribution, exclusions and preference/account boundaries.
- New behavior tests were observed failing before implementation.
- Full hosted build: 5 tasks pass. Typecheck: 8 tasks pass.
- Edition boundary check passes. Independent review found header overlap and distant error feedback; both were corrected and regression-tested.
- No interactive browser verification was performed under the repository's browser-use instruction. Automated DOM tests do not prove visual appearance.
Production release and CI results are recorded in the pull request and task report. No server schema, recommendation rollout flag, Redis quota or Railway variable change is part of this release.
