From b18814faaadd03e28a2c1fd0ed7bf505681b62f5 Mon Sep 17 00:00:00 2001 From: Jeremias Menichelli Date: Mon, 1 Jun 2026 13:00:36 +0200 Subject: [PATCH] Revert "fix: move reference pages to hash navigation and apply redirect rules" (#46541) --- apps/docs/features/docs/Reference.apiPage.tsx | 2 +- apps/docs/features/docs/Reference.cliPage.tsx | 2 +- .../features/docs/Reference.introduction.tsx | 2 +- .../docs/Reference.navigation.client.tsx | 48 +++++++++++-------- apps/docs/features/docs/Reference.sdkPage.tsx | 6 ++- .../docs/features/docs/Reference.sections.tsx | 4 +- .../docs/Reference.selfHostingPage.tsx | 2 +- apps/docs/next.config.mjs | 14 ------ apps/www/lib/redirects.js | 14 ------ 9 files changed, 40 insertions(+), 54 deletions(-) diff --git a/apps/docs/features/docs/Reference.apiPage.tsx b/apps/docs/features/docs/Reference.apiPage.tsx index e1bd542dc98..3e77558f3e6 100644 --- a/apps/docs/features/docs/Reference.apiPage.tsx +++ b/apps/docs/features/docs/Reference.apiPage.tsx @@ -9,7 +9,7 @@ import { SidebarSkeleton } from '~/layouts/MainSkeleton' export async function ApiReferencePage() { return ( - + + diff --git a/apps/docs/features/docs/Reference.navigation.client.tsx b/apps/docs/features/docs/Reference.navigation.client.tsx index 3e991fd6dc1..75e2ea65fb2 100644 --- a/apps/docs/features/docs/Reference.navigation.client.tsx +++ b/apps/docs/features/docs/Reference.navigation.client.tsx @@ -6,6 +6,7 @@ import { BASE_PATH } from '~/lib/constants' import { debounce } from 'lodash-es' import { ChevronUp } from 'lucide-react' import Link from 'next/link' +import { usePathname } from 'next/navigation' import { Collapsible } from 'radix-ui' import type { HTMLAttributes, MouseEvent, PropsWithChildren } from 'react' import { @@ -36,7 +37,6 @@ function subscribeToPathname(callback: () => void) { if (patchCount === 0) { window.addEventListener('popstate', notifyPathnameListeners) - window.addEventListener('hashchange', notifyPathnameListeners) originalPushState = history.pushState.bind(history) history.pushState = (...args) => { @@ -58,7 +58,6 @@ function subscribeToPathname(callback: () => void) { if (patchCount === 0) { window.removeEventListener('popstate', notifyPathnameListeners) - window.removeEventListener('hashchange', notifyPathnameListeners) history.pushState = originalPushState! history.replaceState = originalReplaceState! originalPushState = null @@ -67,29 +66,40 @@ function subscribeToPathname(callback: () => void) { } } -function getLocation() { +function getPathname() { if (typeof window === 'undefined') return '' const pathname = window.location.pathname - const strippedPathname = pathname.startsWith(BASE_PATH) - ? pathname.slice(BASE_PATH.length) - : pathname - return `${strippedPathname}${window.location.hash}` + return pathname.startsWith(BASE_PATH) ? pathname.slice(BASE_PATH.length) : pathname } -function getServerLocation() { +function getServerPathname() { return '' } -function useCurrentLocation() { - return useSyncExternalStore(subscribeToPathname, getLocation, getServerLocation) +function useCurrentPathname() { + return useSyncExternalStore(subscribeToPathname, getPathname, getServerPathname) } -export function ReferenceContentScrollHandler({ children }: PropsWithChildren) { +export function ReferenceContentScrollHandler({ + libPath, + version, + isLatestVersion, + children, +}: PropsWithChildren<{ + libPath: string + version: string + isLatestVersion: boolean +}>) { const [initiallyScrolled, setInitiallyScrolled] = useState(false) + const pathname = usePathname() + useEffect(() => { if (!initiallyScrolled) { - const initialSelectedSection = window.location.hash.replace(/^#/, '') + const initialSelectedSection = pathname.replace( + `/reference/${libPath}/${isLatestVersion ? '' : `${version}/`}`, + '' + ) if (initialSelectedSection) { const section = document.getElementById(initialSelectedSection) if (section) { @@ -100,7 +110,7 @@ export function ReferenceContentScrollHandler({ children }: PropsWithChildren) { setInitiallyScrolled(true) } - }, [initiallyScrolled]) + }, [pathname, libPath, version, isLatestVersion, initiallyScrolled]) return ( @@ -167,7 +177,7 @@ export function ReferenceNavigationScrollHandler({ } function deriveHref(basePath: string, section: AbbrevApiReferenceSection) { - return 'slug' in section ? `${basePath}#${section.slug}` : '' + return 'slug' in section ? `${basePath}/${section.slug}` : '' } function getLinkStyles(isActive: boolean, className?: string) { @@ -237,10 +247,10 @@ export function RefLink({ }) { const ref = useRef(null) - const location = useCurrentLocation() + const pathname = useCurrentPathname() const href = deriveHref(basePath, section) const isActive = - location === href || (location === basePath && href.replace(basePath, '') === '#introduction') + pathname === href || (pathname === basePath && href.replace(basePath, '') === '/introduction') useEffect(() => { if (ref.current) { @@ -283,15 +293,15 @@ export function RefLink({ function useCompoundRefLinkActive(basePath: string, section: AbbrevApiReferenceSection) { const [open, _setOpen] = useState(false) - const location = useCurrentLocation() + const pathname = useCurrentPathname() const parentHref = deriveHref(basePath, section) - const isParentActive = location === parentHref + const isParentActive = pathname === parentHref const childHrefs = useMemo( () => new Set((section.items || []).map((item) => deriveHref(basePath, item))), [basePath, section] ) - const isChildActive = childHrefs.has(location) + const isChildActive = childHrefs.has(pathname) const isActive = isParentActive || isChildActive diff --git a/apps/docs/features/docs/Reference.sdkPage.tsx b/apps/docs/features/docs/Reference.sdkPage.tsx index 5d095d52034..9f03d453bde 100644 --- a/apps/docs/features/docs/Reference.sdkPage.tsx +++ b/apps/docs/features/docs/Reference.sdkPage.tsx @@ -21,7 +21,11 @@ export async function ClientSdkReferencePage({ sdkId, libVersion }: ClientSdkRef const menuData = NavItems[libraryMeta.meta[libVersion].libId] return ( - + {subcommandDetails.title} diff --git a/apps/docs/features/docs/Reference.selfHostingPage.tsx b/apps/docs/features/docs/Reference.selfHostingPage.tsx index 7fad5fefc0f..53773af3514 100644 --- a/apps/docs/features/docs/Reference.selfHostingPage.tsx +++ b/apps/docs/features/docs/Reference.selfHostingPage.tsx @@ -48,7 +48,7 @@ export async function SelfHostingReferencePage({ const name = REFERENCES[servicePath.replaceAll('-', '_')].name return ( - + /introduction (and versioned variants) - // back to the base reference URL. Order matters: introduction first so - // it strips to a bare URL, then the section rules add a hash anchor. - { - source: '/reference/:lib/:version(v\\d+)/:section', - destination: '/reference/:lib/:version#:section', - permanent: true, - }, - { - source: '/reference/:lib/:section((?!v\\d+$)[^/]+)', - destination: '/reference/:lib#:section', - permanent: true, }, ] }, diff --git a/apps/www/lib/redirects.js b/apps/www/lib/redirects.js index 934a83da7f2..551a7613f9a 100644 --- a/apps/www/lib/redirects.js +++ b/apps/www/lib/redirects.js @@ -3203,20 +3203,6 @@ module.exports = [ destination: '/dashboard/redeem?code=:code', permanent: false, }, - // Reference pages use hash anchors for sections; redirect the legacy - // path-style /docs/reference//introduction (and versioned variants) - // back to the base reference URL. Order matters: introduction first so it - // strips to a bare URL, then the section rules add a hash anchor. - { - permanent: true, - source: '/docs/reference/:lib/:version(v\\d+)/:section', - destination: '/docs/reference/:lib/:version#:section', - }, - { - permanent: true, - source: '/docs/reference/:lib/:section((?!v\\d+$)[^/]+)', - destination: '/docs/reference/:lib#:section', - }, // Legacy product .txt URLs → new .md routes { permanent: true, source: '/llms/homepage.txt', destination: '/homepage.md' }, { permanent: true, source: '/llms/auth.txt', destination: '/auth.md' },