Jekyll Pagination: Configuring Archive Pages Without Broken Links
Jekyll pagination is opt-in and path-sensitive. Learn how `paginate`, `paginate_path`, and Liquid navigation variables interact—and how to verify archive pages before deploying.
13 Oct 2026, 16:43 UTC

The 404 on /page/2/
You added paginate: 3 to _config.yml, rebuilt the site, and expected /page/2/ to exist. Instead, you get a 404, or the page loads but the navigation links point nowhere. The issue is usually not a missing plugin—it is a mismatch between how Jekyll generates archive pages and how your posts declare their URLs.
Jekyll pagination is opt-in, path-sensitive, and limited to _posts unless you configure collections explicitly. Getting it right requires three things: a non-zero paginate value, a paginate_path that matches your permalink strategy, and Liquid navigation that uses the paginated context variables correctly.
Pagination Is Opt-In and Context-Aware
Jekyll does not paginate by default. The paginate setting in _config.yml is the switch: it must be an integer of 1 or greater. Without it, Jekyll generates no numbered archive pages, and the page variable remains absent from the template context. If your index template references page and renders nothing, this is the first place to check.
The value you assign controls how many posts appear per archive page. Some themes expose a separate per_page setting, but the paginate value in _config.yml is what triggers archive generation in the first place.
paginate_path and the Permalink Trap
Since Jekyll 4, paginate_path defaults to /page/:num/. You can customize it using two tokens: %d for the page number and %s for the post slug. For example, /blog/%d/ produces /blog/2/ for the second archive page.
The trap is permalink divergence. If your posts use a custom permalink structure that changes the base URL, the default paginate_path may still resolve, but relative links inside the archive pages can break. More importantly, if you change paginate_path to a pattern that assumes a different URL hierarchy than your posts actually use, Jekyll will happily generate 404s. Always verify that the generated archive URLs align with your post URLs.
Navigation with Liquid Variables
On a paginated page, Jekyll exposes the current page number as page, the total page count as pages, and previous/next navigation values you can test in Liquid. The common pattern is to wrap navigation links in conditionals so they only appear when a previous or next page exists.
{% if page.previous %}
<a href="{{ page.previous }}">Previous</a>
{% endif %}
{% if page.next %}
<a href="{{ page.next }}">Next</a>
{% endif %}
Because page is absent when pagination is disabled, these conditionals fail silently on a non-paginated site. That is usually the desired behavior, but it means a typo in the variable name will not raise an error—it will simply hide the navigation.
Collections and the _posts Boundary
This is the limitation that surprises most teams: paginate applies to _posts by default. If you store content in a custom collection—say, _articles or _docs—Jekyll will not paginate it unless you set paginate: N explicitly within that collection's configuration in _config.yml.
Jekyll 3 and Jekyll 4 also differ in how paginate interacts with collections. If you are maintaining a site across major versions, confirm the collection behavior against your installed Jekyll version rather than assuming the old rules still apply.
Worked Example: Seven Posts, Three Per Page
Suppose you have seven dated Markdown files in _posts and you want three posts per archive page. Add the following to _config.yml:
paginate: 3
paginate_path: "/page/:num/"
Run the build from your site root. You need write access to the _site/ output directory:
jekyll build
After the build completes, check that the archive directories exist. You should see _site/page2/index.html and _site/page3/index.html. Open _site/page2/index.html and confirm it contains the fourth, fifth, and sixth posts. Open _site/page3/index.html and confirm it contains only the seventh post.
Next, serve the site locally and inspect the rendered HTML at http://localhost:4000/page/2/. Verify that the previous link points to page 1 and the next link points to page 3. If either link is missing or malformed, the most likely cause is a paginate_path that does not match your post permalink structure.
| Check | Expected Result |
|---|---|
_site/page2/index.html exists | Posts 4–6 rendered |
_site/page3/index.html exists | Post 7 rendered |
| Page 2 source contains prev link | Points to /page/1/ or site root |
| Page 2 source contains next link | Points to /page/3/ |
If you change paginate_path later, the old archive URLs will no longer be generated. That is a state change: external links and search indexes may break. Update your navigation templates and, if necessary, add redirects before rebuilding.
A Practical Verification Habit
Before deploying, treat pagination as a build-time contract. Confirm that paginate is set, that paginate_path tokens match your URL strategy, and that the Liquid conditionals render correctly on the middle archive page—not just the first. The middle page is the only one that exercises both previous and next navigation.
If you are working with collections other than _posts, verify the pagination behavior against your specific Jekyll version. When in doubt, generate a small test site with known content and inspect the output directories directly.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.