From 67a204de11d756607a0bf5a4ce86c83cd03ce979 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Wed, 13 May 2026 09:48:02 +0530 Subject: [PATCH] feat: enable breadcrumbs and prev/next navigation on API pages - Show breadcrumbs on API routes using the API page tree - Compute prev/next from flattened API tree for arrow navigation - Prev/next buttons navigate between API endpoints within the spec Co-Authored-By: Claude Opus 4.6 (1M context) --- .../chronicle/src/themes/default/Layout.tsx | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/chronicle/src/themes/default/Layout.tsx b/packages/chronicle/src/themes/default/Layout.tsx index 8a6eef7..3d69e3b 100644 --- a/packages/chronicle/src/themes/default/Layout.tsx +++ b/packages/chronicle/src/themes/default/Layout.tsx @@ -21,7 +21,7 @@ import { Breadcrumbs } from '@/components/ui/breadcrumbs'; import { getLandingEntries } from '@/lib/config'; import { getActiveContentDir } from '@/lib/navigation'; import { usePageContext } from '@/lib/page-context'; -import type { Node } from 'fumadocs-core/page-tree'; +import type { Node, Root } from 'fumadocs-core/page-tree'; import type { ThemeLayoutProps } from '@/types'; import styles from './Layout.module.css'; import { OpenInAI } from './OpenInAI'; @@ -71,7 +71,12 @@ export function Layout({ const isApiRoute = pathname === '/apis' || pathname.startsWith('/apis/'); const isApiBase = (basePath: string) => pathname === basePath || pathname.startsWith(`${basePath}/`); - const { prev, next } = page ?? { prev: null, next: null }; + const docNav = page ?? { prev: null, next: null }; + const apiNav = useMemo(() => { + if (!isApiRoute) return { prev: null, next: null }; + return getApiPrevNext(pathname, tree); + }, [isApiRoute, pathname, tree]); + const { prev, next } = isApiRoute ? apiNav : docNav; const contentEntries = getLandingEntries(config, version.dir); const activeContentDir = getActiveContentDir(pathname, config); @@ -200,7 +205,7 @@ export function Layout({ - {!isApiRoute && } + {isApiRoute && } @@ -390,3 +395,21 @@ function ViewDocsButton() { ); } + +function getApiPrevNext(pathname: string, tree: Root): { prev: { url: string; title: string } | null; next: { url: string; title: string } | null } { + const pages: { url: string; title: string }[] = []; + function collect(node: Node) { + if (node.type === 'page') { + pages.push({ url: node.url, title: node.name?.toString() ?? '' }); + } else if (node.type === 'folder') { + for (const child of node.children) collect(child); + } + } + for (const child of tree.children) collect(child); + + const idx = pages.findIndex(p => p.url === pathname); + return { + prev: idx > 0 ? pages[idx - 1] : null, + next: idx >= 0 && idx < pages.length - 1 ? pages[idx + 1] : null, + }; +}