Skip to main content

Documentation Index

Fetch the complete documentation index at: https://kubo-47e69177.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Pagination

Server action contract

app/actions.ts
import { defineAction } from "@zapaction/core";
import { z } from "zod";

export const listTodosPage = defineAction({
  input: z.object({ cursor: z.string().nullable(), limit: z.number().min(1).max(100) }),
  output: z.object({
    items: z.array(z.object({ id: z.string(), title: z.string(), done: z.boolean() })),
    nextCursor: z.string().nullable()
  }),
  handler: async ({ input }) => {
    return {
      items: [],
      nextCursor: input.cursor ? null : "cursor_2"
    };
  }
});

Client infinite query

components/todo-feed.tsx
"use client";

import { useInfiniteQuery } from "@tanstack/react-query";

import { listTodosPage } from "../app/actions";

const query = useInfiniteQuery({
  queryKey: ["todos", "infinite"],
  initialPageParam: null as string | null,
  queryFn: async ({ pageParam }) =>
    listTodosPage({ cursor: pageParam, limit: 20 }),
  getNextPageParam: (lastPage) => lastPage.nextCursor
});

Notes

  • Keep the cursor opaque.
  • Use stable sort order in the backend.
  • Keep limit bounded by schema.