Eleventy Pagination: Slicing Collections at Build Time Without a Plugin
Eleventy’s pagination is a build-time loop declared in front matter. Here is how the size, alias, and permalink mechanics work, and what breaks when datasets grow.
21 Jan 2026, 18:42 UTC

The problem: one template, too many items
You have a growing collection of posts and a single archive template. Rendering every item on one page makes the HTML heavy and the page slow to load. You want /archive/, /archive/page-2/, and so on, but you would rather not pull in a plugin or move pagination to the client. Eleventy’s built-in pagination solves this by turning one template into a set of pages at build time.
The useful takeaway: pagination in Eleventy is not a runtime component. It is a front-matter instruction that slices an array into pages during the build, and you are responsible for wiring the URLs and navigation yourself.
How front-matter pagination works
Pagination is declared in the front matter of any template with a pagination object. Three keys matter most:
datanames the source array. This can be a collection, a JavaScript data file export, or computed data, but by the time pagination runs it must resolve to an array.sizesets how many items appear on each page.aliasgives the current slice a variable name inside the template.
Because Eleventy resolves pagination after the data cascade—the ordered merge of front matter, directory data files, and computed values—you can paginate collections like collections.posts directly. The permalink front matter can reference pagination variables to build distinct URLs, enabling archive-style navigation without a plugin.
A worked example: five posts, two per page
Imagine a site with five posts and a template named archive.njk. The front matter below tells Eleventy to paginate the posts collection with two items per page and expose the current slice as post. The permalink syntax follows your template language; this example uses Nunjucks.
---
pagination:
data: collections.posts
size: 2
alias: post
permalink: "/archive/{% if pagination.pageNumber != 0 %}{{ pagination.pageNumber | plus: 1 }}/{% endif %}"
---
Inside the template body, iterate over the alias:
<ul>
{% for item in post %}
<li><a href="{{ item.url }}">{{ item.data.title }}</a></li>
{% endfor %}
</ul>
With five items and size: 2, Eleventy should emit three pages: /archive/, /archive/2/, and /archive/3/. The first two pages contain two items each; the last contains one.
Eleventy does not automatically generate previous/next links. You must derive them from the page index or alias, and first/last pages often need conditional guards. For example, check whether the current page number is greater than zero before rendering a “Previous” link.
The trade-offs: build time, dead links, and collection gaps
Build cost scales with output count. Paginated pages are rendered at build time. Each page receives its own slice of the source array, so output count scales with dataset size divided by page size, but every page still triggers a full template render. Deeply paginated sites can slow builds; very large datasets may need upstream filtering or external pagination.
Size larger than the dataset. If size exceeds the dataset length, Eleventy still emits at least one page. URL patterns that assume multiple pages can produce dead links if your navigation logic does not guard against a single page.
Collection membership. By default, paginated pages may not join collections. The addAllPagesToCollections option alters whether paginated pages join collections; without it, authors may find those pages missing from sitemaps or feeds.
Permalink collisions. Pagination aliases and permalink patterns can collide with existing static routes if the generated paths overlap. Check your output directory for overwritten files.
Verify before you ship
Run these commands from your project root, where package.json lives. No special permissions are required beyond write access to the output directory.
- Check the installed version:
Pagination defaults and configuration have evolved across Eleventy major versions, including ESM support and Node requirements. Compare behavior against the documentation for that release.npx @11ty/eleventy --version - Build the site:
Expected check: the build completes without errors, and your output directory (commonlynpx @11ty/eleventy_site/) contains the paginated URLs. - Inspect the fixture. With five items and
size: 2, confirm the output contains three HTML files with the expected slices and no duplicate aliases.
If you need to revert a test build, delete the generated output directory or point --output to a temporary folder:
npx @11ty/eleventy --output=_tmp_test
Closing
Start with a small fixture, confirm the URL pattern and slice contents, then measure build time as the dataset grows. If builds become slow, filter the source array upstream rather than paginating an already-large collection. Pagination is a powerful build-time tool, but it trades template complexity for static output.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.