Collection Pagination Design
Goal
Add pagination to collection index pages, displaying 50 items at a time using Astro’s built-in paginate() function.
Scope
- All collection index pages (e.g.
/projects,/guides,/links) - All category-filtered pages (e.g.
/projects/web-apps,/links/tools) - 50 items per page
- Simple prev/next button UI
Route Structure Changes
| Current | New | URLs Generated |
|---|---|---|
[collection]/index.astro | [collection]/[...page].astro | /projects, /projects/2, /projects/3 |
[collection]/[category].astro | [collection]/[category]/[...page].astro | /projects/web, /projects/web/2 |
The [...page] rest parameter gives clean URLs: page 1 has no number suffix.
Approach
Use Astro’s native paginate() in getStaticPaths(). This generates static pages at build time — one per 50-item chunk — with a page prop containing:
page.data— items for the current pagepage.url.prev/page.url.next— navigation URLspage.total— total item count across all pagespage.currentPage/page.lastPage— page positionpage.size— page size (50)
Component Changes
Route Pages
[collection]/[...page].astro: Callpaginate(items, { pageSize: 50, params: { collection } })ingetStaticPaths()[collection]/[category]/[...page].astro: Same pattern, filtering items by category first
CollectionGrid
- Receives paginated items (current page slice) plus pagination metadata
- New props:
prevUrl,nextUrl,currentPage,lastPage itemCountstill shows total count (not per-page count)- Renders Pagination component below the grid
Pagination Component (New)
- Simple prev/next buttons
- Shows “Page X of Y”
- Only renders when
lastPage > 1 - Styled consistently with existing UI (tailwind, font-body, teal accent)
What Doesn’t Change
nav-data.ts— still returns all items- Card components — no changes
- Masonry layout — works the same on fewer items
- Post pages (
[collection]/post/[...id].astro) — no changes - CategoryFilter — links stay as
/${collection}/${category}(always page 1)