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: []
}

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