Implementing Astro Pagination for Large Data


When I was building the MCP directory for Free DevTools, I ran into a problem: loading 13,000+ repositories from JSON at once was painfully slow.

I initially tried to build a custom pagination component, but it didn’t work efficiently — everything had to load at once before the UI even appeared.

That’s when I started digging into Astro’s built-in pagination system — and it turned out to be the perfect solution for large collections.



The Problem: Heavy Data Rendering

If you’ve ever fetched a big dataset (thousands of items) and tried to render it in one go, you’ve seen what happens:

  • The page freezes or crashes during hydration.
  • Memory spikes.
  • Scrolling becomes laggy.
  • Static build times increase drastically.

In my case, the MCP directory had 13k+ items coming from JSON. I needed pagination that could:

  • Split data into multiple pages.
  • Load only what’s needed.
  • Still be SEO-friendly (pre-rendered static pages).



Enter Astro Pagination

Astro has first-class support for pagination, directly built into its file-based routing system.

You don’t need a client-side library or heavy runtime logic — it’s done at build time.

You can read the full guide here: Astro Pagination Docs



Basic Pagination Setup

To paginate data, you need a file under src/pages/ with [page].astro in its name.

Example:
src/pages/mcp/[page].astro

This tells Astro to automatically generate:

/mcp/1
/mcp/2
/mcp/3
...
Enter fullscreen mode

Exit fullscreen mode



Example Code

---
export async function getStaticPaths({ paginate }) {
  // Fetch or import your large dataset
  const response = await fetch("https://api.example.com/data");
  const data = await response.json();

  // Each page will show 20 items
  return paginate(data.items, { pageSize: 20 });
}

const { page } = Astro.props;
---



    {page.data.map((item) => (
  • {item.name}
  • ))}
Enter fullscreen mode

Exit fullscreen mode

That’s it. Astro automatically:

  • Slices the data into chunks of pageSize.
  • Builds each page statically.
  • Provides navigation URLs (page.url.prev, page.url.next, etc.).



Items per Page

You control how many items appear per page using the pageSize option in paginate().

Example:

return paginate(data, { pageSize: 10 });
Enter fullscreen mode

Exit fullscreen mode

That will generate:

  • /1 → items 1–10
  • /2 → items 11–20
  • /3 → items 21–30, and so on.

For my MCP project, I used 50 items per page to balance between page size and build speed.




Page Prop Explained

Every generated page receives a page prop with all the info you need.

Property Description
page.data Array of items for this page
page.currentPage Current page number
page.lastPage Total number of pages
page.size Number of items per page
page.total Total items in all pages
page.url.current URL of the current page
page.url.next URL of next page (if available)
page.url.prev URL of previous page (if available)
page.url.first URL of first page
page.url.last URL of last page

Example usage:

Showing {page.start + 1}–{page.end} of {page.total} items

Enter fullscreen mode

Exit fullscreen mode




Navigation Links (Next/Prev/First/Last)

You can easily build full navigation using the provided URLs:


Enter fullscreen mode

Exit fullscreen mode

Astro only generates the relevant links, so no need to manually check page numbers.



Nested Pagination (Optional)

You can even combine pagination with other dynamic routes.

Example:
If you want paginated lists grouped by category, create /src/pages/webdev/[page].astro.

---
export async function getStaticPaths({ paginate }) {
  const categories = ["frontend", "backend"];
  const allItems = await fetchItems();

  return categories.flatMap((category) => {
    const filtered = allItems.filter((item) => item.category === category);
    return paginate(filtered, {
      params: { category },
      pageSize: 10,
    });
  });
}

const { page } = Astro.props;
const { category } = Astro.params;
---


    {page.data.map((item) =>
  • {item.name}
  • )}
Enter fullscreen mode

Exit fullscreen mode

This generates:

/frontend/1
/frontend/2
/backend/1
/backend/2
Enter fullscreen mode

Exit fullscreen mode



Why It’s Better

āœ… Fully static — great for SEO.
āœ… No client-side pagination logic or JS required.
āœ… Easy to maintain, no state management.
āœ… Works perfectly with Markdown collections, APIs, or JSON files.

For my MCP directory, moving from client-side pagination to Astro’s native pagination made the site load much faster and lighter. Each page now loads instantly and only processes a small chunk of data.



Conclusion

Astro’s pagination is simple, fast, and built for static scalability.

Whether you’re handling Markdown posts, API responses, or JSON data — it gives you a clean way to manage large datasets without overloading the browser.

If you’re building something like my Free DevTools MCP directory, give Astro’s pagination a try.

It’s one of those small features that completely changes how efficiently you can build large-scale static pages.

FreeDevTools

Any feedback or contributors are welcome!

It’s online, open-source, and ready for anyone to use.

šŸ‘‰ Check it out: FreeDevTools
⭐ Star it on GitHub: freedevtools



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *