Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Pagination

Pagination splits a long list into pages of a few entries each: /posts/page/1, /posts/page/2 and so on. Astro has the paginate() function for this. It arrives as an argument of getStaticPaths() and works out by itself how many pages are needed.

A numbered page

Create src/pages/posts/page/[page].astro. The parameter is called page and holds the page number:

---
import { getCollection } from 'astro:content';
import BaseLayout from '../../../layouts/BaseLayout.astro';
import PostCard from '../../../components/PostCard.astro';
 
export async function getStaticPaths({ paginate }) {
  const posts = (await getCollection('blog'))
    .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
 
  return paginate(posts, { pageSize: 5 });
}
 
const { page } = Astro.props;
---
 
<BaseLayout title={`Posts, page ${page.currentPage}`}>
  <h1>Posts</h1>
  {page.data.map((post) => (
    <PostCard title={post.data.title} url={`/posts/${post.id}`} />
  ))}
</BaseLayout>

With 12 posts the build creates three pages: /posts/page/1 with five posts, /posts/page/2 with five and /posts/page/3 with two. Open /posts/page/1 to check.

The page object

paginate() passes each page a page prop:

FieldWhat it holds
page.dataEntries of the current page
page.currentPageCurrent page number, starting at 1
page.lastPageLast page number
page.totalTotal number of entries
page.url.prevPrevious page address or undefined
page.url.nextNext page address or undefined

Add navigation below the list of posts in the same file:

<nav>
  {page.url.prev && <a href={page.url.prev}>Newer</a>}
  <span>Page {page.currentPage} of {page.lastPage}</span>
  {page.url.next && <a href={page.url.next}>Older</a>}
</nav>

The first page has no "Newer" link, the last one has no "Older" link. The && condition renders a link only when the address exists.

Linking to the list

The first page of the list now lives at /posts/page/1. Put it in the header navigation instead of /posts; the old src/pages/posts/index.astro can be deleted or kept as a short list of recent posts.

Common mistake

People name the file src/pages/posts/[page].astro, next to src/pages/posts/[id].astro. Both files claim addresses like /posts/something, and a post named 2 would clash with the second page of the list. Keep pagination in a separate folder, such as posts/page/, so the addresses do not overlap.

Thanks for reading!

Donate to the site — we work hard for you.