Recipe

Relay-style pagination

Cursor-based pagination is the only way to safely walk a feed that grows while you read it. Meridian implements the Relay Connection spec verbatim: every list field returnsedgeswith stable cursors and apageInfoobject you can trust. This recipe shows the canonical pattern.

1. Ask for the first page

Passfirst: Nand omitafter. The server returns up to N edges plus aendCursoropaque token. Treat the cursor as a black box; do not parse it.

2. Follow the cursor forward

On each subsequent request, pass the previousendCursorasafter. Stop whenpageInfo.hasNextPageis false. The server guarantees no duplicates and no gaps even if rows are inserted between requests.

3. Cache by cursor, not by offset

Because cursors are stable identities, a(field, after)tuple is a safe cache key. Offset-based caches go stale the moment a row is inserted; cursor caches never do.

// Relay-style cursor pagination with Meridian
const query = `
  query Feed($first: Int!, $after: String) {
    feed(first: $first, after: $after) {
      edges {
        cursor
        node { id title createdAt }
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
`;

async function fetchPage(cursor) {
  const res = await fetch('https://api.meridian.dev/graphql', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query,
      variables: { first: 20, after: cursor },
    }),
  });
  const { data } = await res.json();
  return data.feed;
}

// Walk every page until exhausted
let cursor = null;
do {
  const page = await fetchPage(cursor);
  for (const edge of page.edges) handle(edge.node);
  cursor = page.pageInfo.hasNextPage ? page.pageInfo.endCursor : null;
} while (cursor);