GET /feed?cursor=abc&limit=20
{
"items": [{ "id": "p1", "author": {...}, "text": "...",
"media": [{ "url": "...", "w": 1200, "h": 800 }],
"likeCount": 12, "likedByMe": false }],
"nextCursor": "def"
}
Use cursor pagination, an IntersectionObserver to load more, an infinite query cache, and virtualization once the list grows.
Requirements:
- Scroll a personalised feed.
- Load more on scroll.
- Create posts, like and comment.
- See new posts.
Non-functional: fast first paint, smooth scroll on mobile, accessible, and works on poor networks.
Architecture: FeedPage holds a Composer and a FeedList of PostCards. A sentinel (an empty element) sits at the bottom of the list. IntersectionObserver watches it and fetches the next page when it comes into view. Server state lives in an infinite query cache. Post entities can be normalised (stored once by id), so a like updates every place the post appears.
API: cursor pagination, because new posts are inserted all the time. Offsets would duplicate or skip items. Each item includes media dimensions and placeholders.
Optimisations:
- SSR (server-side rendering) or stream the first page.
- Virtualize once the list grows large, so only visible posts are in the DOM.
- Lazy load images, with their space reserved.
- Prefetch the next page before the sentinel is reached.
- New posts arrive by polling or SSE (Server-Sent Events). Show a "New posts" pill instead of shifting content under the user.
- Make likes and comments optimistic (update the UI first), with rollback on failure.
- Restore the scroll position when the user returns from a post.
Accessibility: use the feed and article roles, with keyboard navigation between posts.
Trade-offs:
- Virtualization breaks find-in-page.
- Inserting posts in real time conflicts with a stable scroll position.
- Use cursor pagination and an
IntersectionObserversentinel. - Use virtualization, and image dimensions to avoid layout shift.
- Show a "New posts" pill instead of inserting posts automatically.
- Make interactions optimistic, and normalise posts.
- Server-render the first page, and restore the scroll position.