<%
/* /docs/api/hooks: /docs, /docs/api, /docs/api/hooks, each looked up in the navigation */
const parts = stati.page.url.split('/').filter(Boolean);
const crumbs = parts
.map((_, i) => stati.nav.findNode(`/${parts.slice(0, i + 1).join('/')}`))
.filter(Boolean);
%>
<% if (crumbs.length) { %>
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<% crumbs.forEach((crumb, i) => { %>
<li>
<% if (i === crumbs.length - 1) { %>
<span aria-current="page"><%= crumb.title %></span>
<% } else { %>
<a href="<%= crumb.url %>"><%= crumb.title %></a>
<% } %>
</li>
<% }) %>
</ol>
</nav>
<% } %>
On /docs/api/hooks that's Home › Docs › API › Hooks, with each title from the page's front matter. The built-in stati.nav.getBreadcrumbs() gives only API › Hooks there: the navigation tree is flat, with every folder of pages as a node at the top, so its trail starts at the page's own folder.
The same flatness catches you in menus. A subfolder's pages aren't in its parent's children, so look the subfolder up at the top of the tree:
<% const api = stati.nav.tree.find((node) => node.isCollection && node.url === '/docs/api'); %>
<% for (const page of api?.children ?? []) { %>
<a href="<%= page.url %>"><%= page.title %></a>
<% } %>
Every folder on the way needs an index.md, or its crumb links to a page that doesn't exist.
In the Stati docs: Tree shape, findNode() and getBreadcrumbs().