Rendering Navigation
Methanol provides a hierarchical navigation tree via ctx.pagesTree. This tree is automatically scoped to the current navigation root (isRoot) and respects all hidden and exclude rules.
Each node in the tree uses the following structure:
{
type: 'page' | 'directory',
title: '...',
name: '...',
routePath: '/guide/',
routeHref: '/docs/guide/', // Base-aware URL
children: []
}
Sidebar Implementation
The following example demonstrates a recursive sidebar component:
const NavTree = ({ nodes, currentHref }) => (
<ul>
{(nodes || []).map((node) => {
const label = node.title || node.name || node.routePath
if (node.type === 'directory') {
return (
<li>
{node.routeHref ? <a href={node.routeHref}>{label}</a> : <span>{label}</span>}
{node.children?.length ? <NavTree nodes={node.children} currentHref={currentHref} /> : null}
</li>
)
}
const isActive = node.routeHref === currentHref
return (
<li>
<a href={node.routeHref} aria-current={isActive ? 'page' : null}>
{label}
</a>
</li>
)
})}
</ul>
)
export default function PageTemplate({ PageContent, ExtraHead, ctx }) {
return (
<>
<html>
<head>
<ExtraHead />
</head>
<body>
<aside>
<NavTree nodes={ctx.pagesTree} currentHref={ctx.page.routeHref} />
</aside>
<main>
<PageContent />
</main>
</body>
</html>
</>
)
}
Best Practices
- Use
routeHref: Always userouteHreffor navigation links to ensure thesite.baseprefix is correctly applied. - Trailing Slashes: Directory index routes always include a trailing slash in their
routePath(e.g.,/guide/). This is important for path matching and relative link resolution.