Feed List Architecture

Design an infinitely scrolling feed with ranking freshness and resilient UX.

Quick take: Use cursor pagination and virtualization first. / Split canonical server cache from view model.

Production notes: Use stale-while-revalidate for freshness. / Enforce live region announcements for appended content.

TL;DR

Start with cursor pagination plus virtualization, then layer ranking updates and resilient loading states.

Steel thread

Render first page, append older items via cursor, and preserve scroll anchor.

Interactive views

Use React Flow for CCDAO / data-flow diagrams, Framer Motion for pagination-style transitions, and Lucide for consistent icons (also used in the site chrome).

CCDAO pipeline for this case study
Mini Map

Pagination motion (Framer Motion + spring)

Page 1 — newest cursor `abc123`
1 / 3

C - Collect

  • Do we require ranking freshness every few seconds?
  • What is acceptable feed staleness for users on slow networks?
  • Must keyboard users access new items without losing focus?

C - Component structure

  • FeedPage orchestrates query state and route filters.
  • FeedList owns virtualization window.
  • FeedItem handles local interaction state only.

D - Data modeling

  • Canonical entity map keyed by postId.
  • Ordered postIds list per filter for rendering.
  • Cursor checkpoints stored by filter key.

A - API design

  • GET /feed?cursor=...&limit=...&filter=...
  • POST /reactions with idempotency key.
  • Optional SSE channel for lightweight ranking refresh events.

O - Optimization

  • Virtualize beyond 40 visible cards.
  • Keep image placeholders fixed-size to avoid layout shift.
  • Batch feed update announcements in one polite live region message.
  • virtualization-strategies: keeps render cost stable as items grow.
  • pagination-offset-cursor-infinite: protects ordering consistency during inserts.
  • optimistic-ui-rollback: keeps reaction latency low without data corruption.

Failure modes

  • Stale response applies after a newer cursor request and reorders visible items.
  • Personalization timeout returns sparse data and causes sudden content gaps.
  • Dynamic append announces every item and overwhelms screen-reader users.

Testing checklist

Testing + Accessibility Rubric

CategoryLevelRequirementDone When
functionalunitState transitions handle loading, success, empty, and error.Reducer/state machine tests cover all transitions.
functionalintegrationClient correctly maps API contracts into UI-ready view models.Contract fixtures pass with no runtime shape mismatch.
a11yintegrationFull keyboard flow works for primary interaction loop.Tab/Shift+Tab/Enter/Escape scenarios pass for critical controls.
a11ye2eDynamic updates expose meaningful live region announcements.Manual SR checks validate announcement timing and text quality.

Explain it clearly

  • Short version: cursor + virtualization + stale response guard + a11y live region.
  • Longer version: entity cache shape, pagination contract, and resilience fallback.

Production hardening notes

  • Track stale-response discard rate and p95 first-scroll hitch in telemetry.
  • Circuit-break personalization dependencies and degrade to deterministic ordering.

Trade-off Matrix

Add trade-off rows in this section to compare options.

Related Patterns