Multiple Trees
Docs sites are often split into parts, such as “Guides” and “API Reference”: each part has its own sidebar, and previous and next links never cross from one into another. Call defineTree on the same collection several times, with each tree holding only its own pages.
Defining them
// src/lib/docs.ts
const guides = await defineTree(entries, ({ page, dir }) => [page('guides', dir('guides'))]);
const api = await defineTree(entries, ({ page, dir }) => [page('api', dir('api'))]);
export const sections = [
{ label: 'Guides', href: toHref('docs', 'guides'), tree: guides },
{ label: 'API Reference', href: toHref('docs', 'api'), tree: api },
];
sections is your own data, unknown to minidocs. Names, entry pages and whether to add icons are all up to you.
Which tree the current page is in
Find the tree that contains the current page with findPath:
const section = sections.find((section) => findPath(section.tree, id).length > 0) ?? sections[0];
const nav = navState(section.tree, id);
const { prev, next } = neighbors(section.tree, id);
From there, the sidebar and previous and next links use section.tree, written the same way as with a single tree.
Use findPath rather than id.startsWith('api'), so the structure of the trees is written in one place only.
Pages in no tree, such as the home page, fall back to ?? sections[0]; you can show no sidebar for them instead. When a page appears in two trees, find takes the one listed first in sections.
A switcher
The switcher is your own HTML, like a language switcher:
<nav aria-label="Sections">
{sections.map((item) => (
<a href={item.href} aria-current={item === section ? 'true' : undefined}>
{item.label}
</a>
))}
</nav>
Each link points to the entry page of its part, which is not necessarily the current page, so aria-current is true rather than page.
Multilingual sites
Make sections a function of the locale, where t holds your own interface text:
export const sections = (locale: Locale) => [
{ label: t[locale].guides, href: toHref('docs', 'guides', locale), tree: guides[locale] },
{ label: t[locale].api, href: toHref('docs', 'api', locale), tree: api[locale] },
];
llms.txt and search
- llms.txt: generate one per tree, or join the nodes into one:
toLlmsTxt([...guides, ...api], { title }). The top node with children in each tree becomes a section, see llms.txt - Search: write the tree’s name into a filter, such as
data-pagefind-filter={`tree:${section.label}`}, and add radio buttons namedtree, see Filtering by group
When to use multiple collections
Trees of one collection share its URL prefix and frontmatter schema. Content with a different prefix and different fields, such as a changelog under /changelog/ with a date on every release, belongs in another collection, see Multiple Collections.