minidocs

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: 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 named tree, 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.

On this page
Search in
Type to start searching