Recipe

Infinite Scroll

Seamless cursor-based pagination that loads content as the user scrolls — no click-to-load, no page jumps.

1

Cursor endpoint

Expose an API route that accepts a cursor and returns the next page of results plus a new cursor. Use the last item's ID or a timestamp as the cursor — never offset-based pagination for live feeds.

GET /api/feed?cursor=clxj8k2s00001&limit=20
2

Intersection Observer

Place a sentinel element at the bottom of the list. When it enters the viewport, fire the next fetch. Keep a loading flag to prevent duplicate requests.

const observer = new IntersectionObserver(loadMore);
3

Append & dedupe

Append new items to the existing array. Deduplicate by ID in case the cursor boundary shifts. Never replace the entire list — that kills scroll position.

4

Empty & error states

When the API returns an empty array, disconnect the observer — there is nothing left to load. Surface errors with a retry button, not a silent stall.