From 1e9f19965adb24f5ea324411e32818888ef4d7eb Mon Sep 17 00:00:00 2001 From: Marc LeBlanc <7050295+marcleblanc2@users.noreply.github.com> Date: Thu, 17 Sep 2026 04:37:46 -0600 Subject: [PATCH] fix/breadcrumbs: Link only segments that have a page, label them with the page title Breadcrumbs linked every URL prefix and showed raw slugs, so pages such as /code-search/working/saved-searches offered links to /code-search/working (a 404: the directory has no index page) and read "code-search > working > saved-searches". Look each prefix up in allPosts: link it only when a page exists, label it with that page's first heading, render the current page as text with aria-current=page. The component becomes a server component; the client-side /v/ handling is dropped because src/proxy.ts redirects every versioned URL off this site before it renders. Found by the docs site audit in https://ampcode.com/threads/T-01a0ae50-f7f0-779c-aa66-3887c9953e33 Co-authored-by: Amp Amp-Thread-ID: https://ampcode.com/threads/T-01a0aed2-5fbe-7768-85ea-1378bf98f9ff --- src/components/Breadcrumbs.tsx | 106 +++++++++++++++------------------ 1 file changed, 47 insertions(+), 59 deletions(-) diff --git a/src/components/Breadcrumbs.tsx b/src/components/Breadcrumbs.tsx index 2d2d10952..da79d0c06 100644 --- a/src/components/Breadcrumbs.tsx +++ b/src/components/Breadcrumbs.tsx @@ -1,77 +1,65 @@ -'use client'; - import Link from 'next/link'; -import clsx from 'clsx'; import {ChevronRightIcon} from '@heroicons/react/20/solid'; -import {useEffect, useState} from 'react'; -import {usePathname} from 'next/navigation'; - -export function Breadcrumbs({path}: {path: string[]}) { - let pathname = usePathname(); - const [version, setVersion] = useState(null); +import {allPosts} from 'contentlayer/generated'; - const createLink = ({path, index}: {path: string[]; index: number}) => { - let linkPath = `/${path - .slice(0, index + 1) - .map(encodeURIComponent) - .join('/')}`; - return prependVersion(linkPath); - }; +const linkClassName = + 'text-sm font-medium text-gray-500 hover:text-link-light dark:text-gray-400 dark:hover:text-link'; - // Prepends version (if any) to the link path - const prependVersion = (path: string) => { - return version ? `/v/${version}${path}` : path; +// One crumb per path segment. A segment is linked only when a page exists at +// that path (many section directories have no index page), and is labelled +// with that page's first heading instead of its slug. +function crumbFor(path: string[], index: number) { + const segments = path.slice(0, index + 1); + const page = allPosts.find( + post => post._raw.flattenedPath === segments.join('/') + ); + const title: string | undefined = page?.headings?.[0]?.title; + return { + label: title ?? segments[index], + href: page ? `/${segments.map(encodeURIComponent).join('/')}` : null }; +} - // Handle versions - useEffect(() => { - // Extract the version name from the URL path, if any - const segments = pathname.split('/'); - const versionIndex = segments.findIndex(segment => segment === 'v'); - // Versioned link example: - // docs/v/5.1.2/ where versionName = 5.1.2 - const versionName = versionIndex >= 0 && segments[versionIndex + 1]; - if (!versionName) { - setVersion(null); - return; - } - setVersion(versionName); - }, [pathname]); - +export function Breadcrumbs({path}: {path: string[]}) { return ( );