← ClaudeAtlas

paginationlisted

API pagination patterns. Offset-based, cursor-based, keyset pagination. Filtering, sorting, and page metadata. REST and GraphQL pagination implementations. USE WHEN: user mentions "pagination", "paginate", "cursor", "offset", "page size", "next page", "infinite scroll API", "list endpoint" DO NOT USE FOR: frontend infinite scroll UI - use frontend framework skills; database query optimization - use database skills
claude-dev-suite/claude-dev-suite · ★ 33 · AI & Automation · score 80
Install: claude install-skill claude-dev-suite/claude-dev-suite
# Pagination ## Cursor-Based (recommended for large datasets) ```typescript app.get('/api/products', async (req, res) => { const limit = Math.min(parseInt(req.query.limit as string) || 20, 100); const cursor = req.query.cursor as string | undefined; const where: any = {}; if (cursor) { where.id = { gt: cursor }; } const items = await db.product.findMany({ where, take: limit + 1, // Fetch one extra to check hasMore orderBy: { id: 'asc' }, }); const hasMore = items.length > limit; if (hasMore) items.pop(); res.json({ data: items, pagination: { hasMore, nextCursor: hasMore ? items[items.length - 1].id : null, }, }); }); ``` ## Offset-Based (simple, good for small datasets) ```typescript app.get('/api/products', async (req, res) => { const page = Math.max(parseInt(req.query.page as string) || 1, 1); const limit = Math.min(parseInt(req.query.limit as string) || 20, 100); const offset = (page - 1) * limit; const [items, total] = await Promise.all([ db.product.findMany({ skip: offset, take: limit, orderBy: { createdAt: 'desc' } }), db.product.count(), ]); res.json({ data: items, pagination: { page, limit, total, totalPages: Math.ceil(total / limit), hasMore: offset + items.length < total, }, }); }); ``` ## Filtering and Sorting ```typescript app.get('/api/products', async (req, res) => { const { sort = 'createdAt', order = 'desc', category, minPrice, maxPri