diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts
index 7292518fc3b9..0ca795ee13b4 100644
--- a/packages/docusaurus-module-type-aliases/src/index.d.ts
+++ b/packages/docusaurus-module-type-aliases/src/index.d.ts
@@ -37,7 +37,7 @@ declare module '@generated/registry' {
declare module '@generated/routes' {
import type {RouteConfig} from 'react-router-config';
- type Route = {
+ export type Route = {
readonly path: string;
readonly component: RouteConfig['component'];
readonly exact?: boolean;
diff --git a/packages/docusaurus-theme-classic/src/theme/DocBreadcrumbs/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocBreadcrumbs/index.tsx
index 8eecbe54170a..f912aac438a4 100644
--- a/packages/docusaurus-theme-classic/src/theme/DocBreadcrumbs/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/DocBreadcrumbs/index.tsx
@@ -6,7 +6,11 @@
*/
import React, {type ReactNode} from 'react';
-import {ThemeClassNames, useSidebarBreadcrumbs} from '@docusaurus/theme-common';
+import {
+ ThemeClassNames,
+ useSidebarBreadcrumbs,
+ useHomePageRoute,
+} from '@docusaurus/theme-common';
import styles from './styles.module.css';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
@@ -59,6 +63,7 @@ function HomeBreadcrumbItem() {
export default function DocBreadcrumbs(): JSX.Element | null {
const breadcrumbs = useSidebarBreadcrumbs();
+ const homePageRoute = useHomePageRoute();
if (!breadcrumbs) {
return null;
@@ -72,7 +77,7 @@ export default function DocBreadcrumbs(): JSX.Element | null {
)}
aria-label="breadcrumbs">
-
+ {homePageRoute && }
{breadcrumbs.map((item, idx) => (
diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json
index 01e7cde1a8a3..2d1bc0bb156c 100644
--- a/packages/docusaurus-theme-common/package.json
+++ b/packages/docusaurus-theme-common/package.json
@@ -18,6 +18,7 @@
},
"license": "MIT",
"dependencies": {
+ "@docusaurus/module-type-aliases": "2.0.0-beta.15",
"@docusaurus/plugin-content-blog": "2.0.0-beta.15",
"@docusaurus/plugin-content-docs": "2.0.0-beta.15",
"@docusaurus/plugin-content-pages": "2.0.0-beta.15",
@@ -29,7 +30,6 @@
},
"devDependencies": {
"@docusaurus/core": "2.0.0-beta.15",
- "@docusaurus/module-type-aliases": "2.0.0-beta.15",
"@docusaurus/types": "2.0.0-beta.15",
"@testing-library/react-hooks": "^7.0.2",
"fs-extra": "^10.0.0",
diff --git a/packages/docusaurus-theme-common/src/index.ts b/packages/docusaurus-theme-common/src/index.ts
index 40d4536f4fe6..2e0cbbe9eae7 100644
--- a/packages/docusaurus-theme-common/src/index.ts
+++ b/packages/docusaurus-theme-common/src/index.ts
@@ -124,6 +124,8 @@ export {
export {isRegexpStringMatch} from './utils/regexpUtils';
+export {useHomePageRoute} from './utils/routesUtils';
+
export {useColorMode, ColorModeProvider} from './utils/colorModeUtils';
export {
useTabGroupChoice,
diff --git a/packages/docusaurus-theme-common/src/utils/__tests__/routesUtils.test.ts b/packages/docusaurus-theme-common/src/utils/__tests__/routesUtils.test.ts
new file mode 100644
index 000000000000..18a5167ef1ac
--- /dev/null
+++ b/packages/docusaurus-theme-common/src/utils/__tests__/routesUtils.test.ts
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import {type Route} from '@generated/routes';
+import {findHomePageRoute} from '../routesUtils';
+
+describe('routesUtils findHomePageRoute', () => {
+ const homePage: Route = {
+ path: '/',
+ exact: true,
+ };
+
+ test('should return undefined for no routes', () => {
+ expect(findHomePageRoute([])).toEqual(undefined);
+ });
+
+ test('should return undefined for no homepage', () => {
+ expect(
+ findHomePageRoute([
+ {path: '/a', exact: true},
+ {path: '/b', exact: false},
+ {path: '/c', exact: undefined},
+ {
+ path: '/d',
+ exact: false,
+ routes: [
+ {path: '/d/1', exact: true},
+ {path: '/d/2', exact: false},
+ {path: '/d/3', exact: undefined},
+ ],
+ },
+ ]),
+ ).toEqual(undefined);
+ });
+
+ test('should find top-level homepage', () => {
+ expect(
+ findHomePageRoute([
+ {path: '/a', exact: true},
+ {path: '/b', exact: false},
+ {path: '/c', exact: undefined},
+ {...homePage, exact: false},
+ homePage,
+ {...homePage, exact: undefined},
+ ]),
+ ).toEqual(homePage);
+ });
+
+ test('should find nested homepage', () => {
+ expect(
+ findHomePageRoute([
+ {path: '/a', exact: true},
+ {
+ path: '/',
+ exact: false,
+ routes: [
+ {path: '/b', exact: true},
+ {
+ path: '/',
+ exact: false,
+ routes: [{path: '/c', exact: true}, homePage],
+ },
+ ],
+ },
+ {path: '/d', exact: true},
+ ]),
+ ).toEqual(homePage);
+ });
+});
diff --git a/packages/docusaurus-theme-common/src/utils/routesUtils.ts b/packages/docusaurus-theme-common/src/utils/routesUtils.ts
new file mode 100644
index 000000000000..ece1ade95511
--- /dev/null
+++ b/packages/docusaurus-theme-common/src/utils/routesUtils.ts
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import GeneratedRoutes, {type Route} from '@generated/routes';
+import {useMemo} from 'react';
+
+function isHomePageRoute(route: Route): boolean {
+ return route.path === '/' && route.exact === true;
+}
+
+function isHomeParentRoute(route: Route): boolean {
+ return route.path === '/' && route.exact === false;
+}
+
+// Note that all sites don't always have a homepage in practice
+// See https://github.com/facebook/docusaurus/pull/6517#issuecomment-1048709116
+export function findHomePageRoute(
+ routes: Route[] = GeneratedRoutes,
+): Route | undefined {
+ if (routes.length === 0) {
+ return undefined;
+ }
+ const homePage = routes.find(isHomePageRoute);
+ if (homePage) {
+ return homePage;
+ }
+ const indexSubRoutes = routes
+ .filter(isHomeParentRoute)
+ .flatMap((route) => route.routes ?? []);
+ return findHomePageRoute(indexSubRoutes);
+}
+
+export function useHomePageRoute(): Route | undefined {
+ return useMemo(() => findHomePageRoute(), []);
+}