Navigation
The left-hand nav and the prev/next links at the bottom of every page are both driven by a single JSON manifest. Group articles into chapters or list them flat, point the plugin at the file, and the nav, headings, and inter-page links fall out automatically.
The manifest
navigation.json (path configurable via
options.navigation) takes one of two shapes. Most sites
want the chaptered form:
{
"chapters": [
{
"title": "Introduction",
"articles": [
{ "slug": "", "title": "Home" },
{ "slug": "getting-started", "title": "Getting started" }
]
},
{
"title": "Authoring",
"articles": [
{ "slug": "page-structure", "title": "Page structure" },
{ "slug": "code-blocks", "title": "Code blocks" }
]
}
]
}
Each chapter has a title (rendered as a small uppercase
heading in the nav) and an articles array. A flat,
chapter-less site can skip the wrapping and use an array directly:
[
{ "slug": "", "title": "Home" },
{ "slug": "install", "title": "Install" },
{ "slug": "usage", "title": "Usage" }
]The chaptered shape is what the prev/next computation walks — it flattens the chapters in declared order and treats the whole thing as one sequence.
Slug-only entries
Inside an articles array each entry can also be a bare
slug string. The nav loader resolves the title from the target
page’s <h1>, so the manifest doesn’t
repeat what the page already states:
{
"chapters": [
{
"title": "Introduction",
"articles": [ "", "getting-started" ]
},
{
"title": "Authoring",
"articles": [ "page-structure", "code-blocks" ]
}
]
}
Bare strings and {slug, title} objects can be mixed in
the same array — reach for an explicit title only
when the nav label needs to differ from the page heading.
If a slug points at a file that doesn’t exist, or the file has
no <h1>, the slug is used as the title and a
warning is logged so the gap is visible in the build output.
Group dividers
A chapter can carry an optional section string: a divider
label rendered above it in the nav that groups the chapters following
it, up to the next chapter that declares its own section.
It’s a flat marker, not an extra level of nesting — the
prev/next sequence and chapter structure are unaffected.
{
"chapters": [
{ "title": "Introduction", "articles": [ "", "getting-started" ] },
{
"section": "Guides",
"title": "Authoring",
"articles": [ "page-structure", "code-blocks" ]
}
]
}Article entries
- slug
-
The URL path after the site root, without leading or trailing slashes. The empty string
""is the home page (mounted at/). A slug of"getting-started"maps to/getting-started/.Slugs must match the directory structure produced by Eleventy. With the default
contentDir: "src/content"setup, a file atsrc/content/foo/bar.htmlbecomes the slugfoo/bar. - title
-
The label shown in the nav. Optional — when omitted, the loader uses the target page’s
<h1>. Set it explicitly when the nav label needs to differ from the page heading, e.g. nav reads “Install” even though the page itself is titled “Installing @carrotsearch/eleventy-apidocs”. - expand
-
Optional. Surfaces a page’s top-level
<section id>entries as extra links in the nav, listed right after the article at the same level as ordinary pages — so a long reference page (a command list, an env-var list) reads like a chapter whose “pages” are its sections. Each targets/<slug>/#<id>. Pair it with a chapter of its own for the cleanest result.Use
trueto expand the article’s own page, or a slug string to expand a different one:{ "chapters": [ { "section": "Reference", "title": "Reference", "articles": [ { "slug": "api-reference", "expand": true } ] } ] }Children hang off the article as a nested list; they are not separate steps in the prev/next sequence, and search already indexes every section independently, so
expandchanges the sidebar only.
How it renders
The left-hand <nav> walks the chapters in declared
order, prints each title as a small uppercase heading,
and lists each article as a link. The link to the current page gets
an aria-current attribute and a styled background so
visitors always know where they are.
Reordering the manifest reorders the nav. Renaming a chapter renames the heading. The data file is the single source of truth — the content directory is the source of pages, not of order.
Prev/next links
The footer of every article carries a two-column block: the previous article on the left, the next on the right. The sequence is the flattened article list, in manifest order — chapters are transparent for this purpose, so the last article of one chapter points to the first article of the next.
Articles at the ends of the sequence get a half-empty footer: the home page has only a “next”, the last article has only a “previous”. The grid keeps a fixed two-column layout regardless, so the remaining link doesn’t shift position.
Pages whose slug doesn’t appear in navigation.json
still build and are reachable by URL, but they show no prev/next
block. Use this for pages you want to publish but keep out of the
main reading sequence — release notes, error pages, deep-linked
appendices.
Live reloads
The plugin watches the navigation file with
addWatchTarget, so editing
navigation.json during pnpm dev triggers a
rebuild without restarting the server. The logo and footer fragments
are watched the same way.