npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nera-static/plugin-page-pagination

v2.3.1

Published

A plugin for Nera static site generator to create previous/next page pagination within directory structures. Perfect for blog posts, documentation sections, and sequential content navigation.

Readme

@nera-static/plugin-page-pagination

Test npm version

A plugin for the Nera static site generator that creates previous/next navigation between sibling pages. Perfect for documentation sites, tutorials, or any sequential content that needs pagination-style navigation.

✨ Features

  • Automatically generates previous/next links based on sibling pages
  • Supports custom sorting via pagination_order (or custom property)
  • Falls back to creation date when no order is specified
  • Configurable sorting property via config/page-pagination.yaml
  • Deterministic ordering — the result never depends on the order files happen to be read from disk
  • Includes a ready-to-use Pug template
  • Lightweight and easy to integrate
  • Works on Nera v4.1.0+ (see Compatibility)

🚀 Installation

Install the plugin in your Nera project:

npm install @nera-static/plugin-page-pagination

Nera will automatically detect the plugin and inject pagination metadata during the build.

⚙️ Configuration

Customize the order property by creating config/page-pagination.yaml:

order_property: custom_order

This tells the plugin to use custom_order instead of pagination_order.

Example with custom property

---
title: Chapter 1
custom_order: 100
---
---
title: Chapter 2
custom_order: 200
---

🧩 Usage

Automatic sibling pagination

Pages in the same directory are linked in order:

  1. Pages with a pagination_order, sorted by that value
  2. Then pages without one, sorted by creation date
  3. Ties are broken by href, so the result never depends on the order files happen to be read from disk

Mixing the two is safe: every page that defines pagination_order comes before every page that does not. pagination_order: 0 is a valid value and sorts first — it is not treated as "unset".

pagination_order is normally a number, and numeric values — including numeric strings such as '10' — are compared as numbers, so 2 sorts before 10. A non-numeric value (pagination_order: intro) is compared as text instead, which is deterministic but sorts 10 before 2. Do not mix the two styles in one directory unless you have checked the result.

Pages without a layout are excluded

Nera writes a page to public/ only if its frontmatter has a layout, so a page without one is never rendered. Such pages are left out of the pagination chain entirely — they neither appear as a previous/next target nor receive pagination of their own. This matters if you use @nera-static/plugin-stacks, which recommends omitting layout on stack pages: those stacks will not show up as phantom links in a sibling page's navigation.

---
title: Getting Started
pagination_order: 1
---
---
title: Advanced Topics
pagination_order: 2
---

Result:

  • "Getting Started" → Next: "Advanced Topics"
  • "Advanced Topics" → Previous: "Getting Started"

Directory-based grouping

Only pages within the same directory are linked:

pages/
├── docs/
│   ├── intro.md
│   └── start.md
└── blog/
    └── post.md

Template integration

meta.pagePagination is added to each page:

{
  previous: { href: "/docs/intro.html", name: "Introduction" },
  next: { href: "/docs/advanced.html", name: "Advanced Topics" }
}

name is the sibling's title from its frontmatter. A page without a title produces a link with no text, so give every paginated page one.

A missing neighbour is false, not an absent key. The first page in a directory gets { previous: false, next: { … } } and the last gets { previous: { … }, next: false }. Test for truthiness — a check like meta.pagePagination.previous !== undefined is always true.

Use in Pug:

if meta.pagePagination.previous
  a.previous(href=meta.pagePagination.previous.href)
    | ← #{meta.pagePagination.previous.name}

if meta.pagePagination.next
  a.next(href=meta.pagePagination.next.href)
    | #{meta.pagePagination.next.name} →

Pages generated by other plugins

meta.pagePagination is written only onto the pages that exist when this plugin runs. Plugins are applied in the order start: → alphabetical → end:, so a plugin that creates pages and sorts after plugin-page-pagination@nera-static/plugin-tags, which builds its tag overview pages, is the common case — produces pages on which the key is absent entirely.

To paginate those pages too, run this plugin last via config/plugin-order.yaml:

plugin-order:
    - end:
          - plugin-page-pagination

Each tag overview page then gets a previous/next chain across the others in /tags/. Whether you want that is your call; without the entry those pages simply render no pagination.

If you write your own markup instead of using the shipped template, guard the key — it is absent, not empty, so meta.pagePagination.previous on a generated page throws and takes the whole build down. The shipped template does this for you:

- var pagePagination = (typeof meta !== 'undefined' && meta && meta.pagePagination) || {}

if pagePagination.previous
  a.previous(href=pagePagination.previous.href) #{ pagePagination.previous.name }

🛠️ Template Publishing

Use the default template provided by the plugin:

npx nera-page-pagination

This copies the template to:

views/vendor/plugin-page-pagination/page-pagination.pug

Publishing skips when the destination directory views/vendor/plugin-page-pagination/ already exists — the check is on the directory, not on each file. Re-running therefore never discards your edits, but it also copies nothing at all: if you delete a published template and re-run the command, the file is not restored and the command still exits 0.

--force is what delivers a template update. When a release changes the shipped template, upgrading the package does not change the copy under views/vendor/. Your site keeps the old template silently — the upgrade is clean and the new behaviour simply never appears. Re-publish to pick it up:

npx nera-page-pagination --force

This discards any local edits to the published template, so diff first if you have customised it.

Include it in your layout:

include ../vendor/plugin-page-pagination/page-pagination

The path is relative to the including file, so from a layout in views/layouts/ this resolves to views/vendor/…. Adjust the number of ../ segments to match your layout's depth; a bare vendor/… would resolve to views/layouts/vendor/… and fail.

On Nera 4.3.0 and later you can use the location-independent root-absolute form instead, which is resolved relative to views/ and so works from any depth:

include /vendor/plugin-page-pagination/page-pagination

Note there is no views/ segment in it — include /views/vendor/… looks for views/views/vendor/… and fails.

🎨 Styling

The plugin uses BEM CSS methodology:

.page-pagination { }
.page-pagination__link { }
.page-pagination__link--previous { }
.page-pagination__link--next { }

Customize these classes in your CSS.

These class names are a public contract. You hold your own copy of the template under views/vendor/plugin-page-pagination/ and style it from your own CSS, so renaming a class here is a breaking change and only ships in a major release.

📊 Generated Output

The plugin injects pagination metadata into meta.pagePagination; the shipped template renders it as a <nav> block. Rendered by Nera from the templates in this package:

<!-- first page in the directory: next only -->
<nav class="page-pagination"><a class="page-pagination__link page-pagination__link--next" href="/docs/page2.html">Page 2</a></nav>

<!-- middle page: both links -->
<nav class="page-pagination"><a class="page-pagination__link page-pagination__link--previous" href="/docs/page1.html">Page 1</a><a class="page-pagination__link page-pagination__link--next" href="/docs/page3.html">Page 3</a></nav>

<!-- last page: previous only -->
<nav class="page-pagination"><a class="page-pagination__link page-pagination__link--previous" href="/docs/page2.html">Page 2</a></nav>

<!-- page with no siblings: the nav element is still emitted, empty -->
<nav class="page-pagination"></nav>

The empty <nav> in the last case is worth knowing about if you style the block with borders, padding or margins — use .page-pagination:empty to hide it.

If you write your own markup instead, meta.pagePagination is the only data the plugin provides; see Template integration.

🧪 Development

npm install
npx vitest run
npm run lint

npm test starts Vitest in watch mode and does not exit; use npx vitest run for a single pass.

Tests use Vitest and cover:

  • Sibling page detection and grouping
  • Sorting by order property and fallback
  • Previous/next link generation
  • Edge cases (first page, last page, layout-less siblings)
  • Ordering determinism across every input permutation
  • Template rendering, including pages where meta.pagePagination is absent

🤝 Contributing

Issues and pull requests are welcome. See the Nera contributing guide for plugin development, the hook contract, and local setup.

For this repo specifically:

  • npx vitest run and npm run lint must pass (npm test is watch mode).
  • Bump the version and update CHANGELOG.md in the same commit as the change.
  • Template markup and BEM class names are a public contract — users style them from their own CSS, so changing one is a major bump.
  • Releases publish from CI on a pushed v* tag. Never run npm publish.

🧑‍💻 Author

Michael Becker
https://github.com/seebaermichi

🔗 Links

🧩 Compatibility

  • Nera: v4.1.0+ — this is the baseline 4.x floor, not a feature requirement; the plugin uses no generator feature above it. The optional config/plugin-order.yaml entry described under Pages generated by other plugins needs v4.2.0+, where plugin ordering was added; on 4.1.x the file is ignored and plugin-generated pages get no pagination. The optional root-absolute include form needs v4.3.0+; the relative form documented above works on every version.
  • Node.js: >= 20.0.0
  • plugin-utils: ^1.2.0
  • Plugin API: Uses getMetaData() for pagination metadata

📦 License

MIT