Navigation
Build the sidebar from your files, then refine it with frontmatter, folder meta, or config.
Blume builds your sidebar from the file system, then lets you refine it as much — or as little — as you want: page by page, folder by folder, or with one explicit config. Breadcrumbs, previous/next links, and the on-page outline all follow from the same model, with nothing to wire up.
The generated sidebar
By default the sidebar mirrors your content tree:
- folders become groups, files become pages
- a page’s label is its frontmatter
title; a group’s label is the humanized folder name - items sort by numeric prefix, then alphabetically, and a folder’s
indexpage comes first
That’s enough for many sites — everything below is opt-in.
Page label, icon, and badge
Tune how a single page appears in the sidebar from its frontmatter, under sidebar:
sidebar:
label: Quickstart # override the title in the sidebar
icon: rocket # an icon from Blume's built-in set
badge: New # a small label beside the entry
order: 1 # sort position within its group
See Frontmatter for the full page schema.
Folder groups
Each folder becomes a sidebar group. Drop a meta.ts beside its pages to set the group’s title, icon, order, and the order of its children:
import { defineMeta } from "blume";
export default defineMeta({
title: "Guides",
icon: "book-open",
pages: ["configuration", "theming", "deployment"],
});
See Folder meta for every field and computing meta at scan time.
To group pages without adding a URL segment, use a parenthesized folder name — see Pages.
Display modes
navigation.sidebar.display sets how every sidebar group renders:
navigation: {
sidebar: {
display: "flat", // "flat" | "group" | "page"
},
}
flat(default) — a non-collapsible header with its pages listed beneath. Pages that aren’t in any group always list first, above the group sections, so they can’t be mistaken for a group’s children.group— a collapsible<details>disclosure per group. Groups start collapsed by default; a group containing the current page always starts open, so only the section you’re in is expanded. Setcollapsed: falsein folder meta to force a group open regardless.page— each group is a single row that, when clicked, slides the sidebar into a sub-panel showing only that group’s items, with a back arrow at the top. The panel is route-aware, so landing directly on a page inside the group opens straight to it.
A group in an explicit sidebar can override the global mode with its own display.
Ordering
When the sidebar is generated, order is resolved highest priority first:
Config sidebar
An explicit navigation.sidebar replaces the generated tree entirely.
Folder meta
The pages array in meta.ts orders a group.
Frontmatter
sidebar.order on a page.File system
An index page first, then numeric prefixes, then alphabetical by label.
Hidden pages
Hide a page from the sidebar — and from previous/next pagination — while keeping it built and reachable by its URL:
sidebar:
hidden: true
Tabs
Render top-level sections as tabs in the header, useful for splitting a large site into distinct areas — say adapters, an API, and AI guides. A tab is highlighted when the current route falls under its path:
navigation: {
tabs: [
{ label: "Adapters", path: "/adapters", icon: "plug" },
{ label: "API", path: "/api", icon: "rocket" },
{ label: "AI", path: "/ai", icon: "sparkles" },
],
}
Tabs also scope the sidebar: when the current route falls under a tab’s path, the sidebar shows only that section’s pages — so /adapters/* lists the adapters and nothing else. The folder at a tab’s path becomes the section, so this needs no extra config beyond the tabs themselves; structure your content into a folder per tab and point each tab at it.
On a route under no tab (or a tab whose path is /), the sidebar shows the pages that don’t belong to a tab — each tab’s folder is hidden from it, since that section already has its own tab in the header. So a root landing page lists your loose top-level pages while the sectioned content stays behind its tab, mirroring Fumadocs’ root folders. If a route has no pages of its own to show this way, the full tree is shown instead, so the sidebar is never left blank.
Selectors
For switching between whole partitions of a site — a product, a version, or any grouped set of destinations — add a selector. Each renders as a dropdown in the header, showing the option whose path matches the current route:
navigation: {
selectors: [
{
kind: "version",
label: "Version",
items: [
{ label: "v2 (latest)", path: "/v2", icon: "rocket" },
{ label: "v1", path: "/v1" },
],
},
],
}
Each item takes a label, a path, and optional icon, description, and tag. kind (dropdown, product, version, or language) is a hint for how the selector is used; all render the same dropdown.
Featured links
Pin links to the top of the sidebar, above every section — a blog, a changelog, a contact or support page that should always be one click away. Unlike the generated tree, featured links are not scoped by tab: they show on every route, on every breakpoint.
navigation: {
featured: [
{ label: "Blog", href: "https://example.com/blog", icon: "newspaper" },
{ label: "Contact", href: "/contact", icon: "headphones" },
],
}
Each link takes a label, an href, and an optional icon (a built-in icon name, image path/URL, or inline SVG — the same as anywhere else). An href may point anywhere: an external URL opens in a new tab, while an internal route (/contact) is validated against your pages at build time, warning you if nothing matches.
Explicit sidebar
For full control, list explicit items in navigation.sidebar — a bare array is shorthand for sidebar.items, and the object form combines them with a global display. When items are set, Blume uses them verbatim and skips file-system generation:
navigation: {
sidebar: [
"/", // a page, referenced by route
{
label: "Guides", // a group
collapsed: false,
items: ["/configuration", "/configuration/theming"],
},
{ label: "GitHub", href: "https://github.com/owner/repo" }, // an external link
],
}
Each item is a page route (a string), a group (label + items), or a link (label + href). Groups can nest, override the global display mode, and start collapsed.
Repository link
When you set github in your config, Blume shows a GitHub icon in the header — beside the theme toggle — that links to your repository. It’s on by default; hide it with navigation.repo:
navigation: {
repo: false, // hide the header GitHub link (default: true)
}
The link only appears when github is configured, so projects without a repo are unaffected either way.
Breadcrumbs and pagination
These come for free from the sidebar tree — no configuration:
- Breadcrumbs show the current page’s parent group above the title.
- Previous and next links at the foot of each page follow sidebar order, skipping hidden pages.
On this page
A right-rail outline is generated automatically from each page’s ## and ### headings, so long pages stay scannable. On narrower screens, where the right rail is hidden, it collapses into an “On this page” dropdown above the content.
Page actions
Below the table of contents, every page shows a set of quick actions:
- Edit this page on GitHub — links straight to the source file. Appears once you set
githubin your config. - Scroll to top — smoothly returns to the top of long pages.
- Give feedback — opens a prefilled GitHub issue with an optional reaction and note (also requires
github).
Three more hand the page to AI tools — Copy as Markdown, Open in chat, and Ask AI about this page — covered in AI.
With export on, an Export action also lets readers download the page as a PDF or EPUB.