diff --git a/packages/docusaurus-plugin-content-blog/package.json b/packages/docusaurus-plugin-content-blog/package.json
index 81b398107e59..e01d774d0b91 100644
--- a/packages/docusaurus-plugin-content-blog/package.json
+++ b/packages/docusaurus-plugin-content-blog/package.json
@@ -4,9 +4,21 @@
"description": "Blog plugin for Docusaurus.",
"main": "lib/index.js",
"types": "src/plugin-content-blog.d.ts",
+ "exports": {
+ "./lib/*": "./lib/*",
+ "./src/*": "./src/*",
+ "./client": {
+ "type": "./lib/client/index.d.ts",
+ "default": "./lib/client/index.js"
+ },
+ ".": {
+ "types": "./src/plugin-content-blog.d.ts",
+ "default": "./lib/index.js"
+ }
+ },
"scripts": {
- "build": "tsc",
- "watch": "tsc --watch",
+ "build": "tsc --build",
+ "watch": "tsc --build --watch",
"test:generate-build-snap": "yarn docusaurus build src/__tests__/__fixtures__/website --out-dir build-snap && yarn rimraf src/__tests__/__fixtures__/website/.docusaurus && yarn rimraf src/__tests__/__fixtures__/website/build-snap/assets && git add src/__tests__/__fixtures__/website/build-snap"
},
"repository": {
diff --git a/packages/docusaurus-plugin-content-blog/src/client/index.ts b/packages/docusaurus-plugin-content-blog/src/client/index.ts
new file mode 100644
index 000000000000..333ddc5a4d7b
--- /dev/null
+++ b/packages/docusaurus-plugin-content-blog/src/client/index.ts
@@ -0,0 +1,20 @@
+/**
+ * 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 useRouteContext from '@docusaurus/useRouteContext';
+import type {BlogMetadata} from '@docusaurus/plugin-content-blog';
+
+export function useBlogMetadata(): BlogMetadata {
+ const routeContext = useRouteContext();
+ const blogMetadata = routeContext?.data?.blogMetadata;
+ if (!blogMetadata) {
+ throw new Error(
+ "useBlogMetadata() can't be called on the current route because the blog metadata could not be found in route context",
+ );
+ }
+ return blogMetadata as BlogMetadata;
+}
diff --git a/packages/docusaurus-plugin-content-blog/src/index.ts b/packages/docusaurus-plugin-content-blog/src/index.ts
index 770a468f297a..35d6ac6b34db 100644
--- a/packages/docusaurus-plugin-content-blog/src/index.ts
+++ b/packages/docusaurus-plugin-content-blog/src/index.ts
@@ -42,6 +42,7 @@ import type {
BlogTags,
BlogContent,
BlogPaginated,
+ BlogMetadata,
} from '@docusaurus/plugin-content-blog';
export default async function pluginContentBlog(
@@ -182,6 +183,7 @@ export default async function pluginContentBlog(
blogArchiveComponent,
routeBasePath,
archiveBasePath,
+ blogTitle,
} = options;
const {addRoute, createData} = actions;
@@ -257,6 +259,15 @@ export default async function pluginContentBlog(
),
);
+ const blogMetadata: BlogMetadata = {
+ blogBasePath: normalizeUrl([baseUrl, routeBasePath]),
+ blogTitle,
+ };
+ const blogMetadataPath = await createData(
+ `blogMetadata-${pluginId}.json`,
+ JSON.stringify(blogMetadata, null, 2),
+ );
+
// Create routes for blog entries.
await Promise.all(
blogPosts.map(async (blogPost) => {
@@ -276,6 +287,9 @@ export default async function pluginContentBlog(
sidebar: aliasedSource(sidebarProp),
content: metadata.source,
},
+ context: {
+ blogMetadata: aliasedSource(blogMetadataPath),
+ },
});
blogItemsToMetadata[id] = metadata;
diff --git a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
index 7443e14e1621..f8b0bd3123ae 100644
--- a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
+++ b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
@@ -5,6 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/
+///
+
declare module '@docusaurus/plugin-content-blog' {
import type {LoadedMDXContent} from '@docusaurus/mdx-loader';
import type {MDXOptions} from '@docusaurus/mdx-loader';
@@ -466,6 +468,13 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
blogTagsListPath: string;
};
+ export type BlogMetadata = {
+ /** the path to the base of the blog */
+ blogBasePath: string;
+ /** title of the overall blog */
+ blogTitle: string;
+ };
+
export type BlogTags = {
[permalink: string]: BlogTag;
};
@@ -537,6 +546,7 @@ declare module '@theme/BlogPostPage' {
BlogPostFrontMatter,
BlogSidebar,
PropBlogPostContent,
+ BlogMetadata,
} from '@docusaurus/plugin-content-blog';
export type FrontMatter = BlogPostFrontMatter;
@@ -548,6 +558,8 @@ declare module '@theme/BlogPostPage' {
readonly sidebar: BlogSidebar;
/** Content of this post as an MDX component, with useful metadata. */
readonly content: Content;
+ /** Metadata about the blog. */
+ readonly blogMetadata: BlogMetadata;
}
export default function BlogPostPage(props: Props): JSX.Element;
@@ -557,6 +569,10 @@ declare module '@theme/BlogPostPage/Metadata' {
export default function BlogPostPageMetadata(): JSX.Element;
}
+declare module '@theme/BlogPostPage/StructuredData' {
+ export default function BlogPostStructuredData(): JSX.Element;
+}
+
declare module '@theme/BlogListPage' {
import type {Content} from '@theme/BlogPostPage';
import type {
@@ -579,6 +595,28 @@ declare module '@theme/BlogListPage' {
export default function BlogListPage(props: Props): JSX.Element;
}
+declare module '@theme/BlogListPage/StructuredData' {
+ import type {Content} from '@theme/BlogPostPage';
+ import type {
+ BlogSidebar,
+ BlogPaginatedMetadata,
+ } from '@docusaurus/plugin-content-blog';
+
+ export interface Props {
+ /** Blog sidebar. */
+ readonly sidebar: BlogSidebar;
+ /** Metadata of the current listing page. */
+ readonly metadata: BlogPaginatedMetadata;
+ /**
+ * Array of blog posts included on this page. Every post's metadata is also
+ * available.
+ */
+ readonly items: readonly {readonly content: Content}[];
+ }
+
+ export default function BlogListPageStructuredData(props: Props): JSX.Element;
+}
+
declare module '@theme/BlogTagsListPage' {
import type {BlogSidebar} from '@docusaurus/plugin-content-blog';
import type {TagsListItem} from '@docusaurus/utils';
diff --git a/packages/docusaurus-plugin-content-blog/tsconfig.client.json b/packages/docusaurus-plugin-content-blog/tsconfig.client.json
new file mode 100644
index 000000000000..5d06aa818c96
--- /dev/null
+++ b/packages/docusaurus-plugin-content-blog/tsconfig.client.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "noEmit": false,
+ "composite": true,
+ "incremental": true,
+ "tsBuildInfoFile": "./lib/.tsbuildinfo-client",
+ "moduleResolution": "bundler",
+ "module": "esnext",
+ "target": "esnext",
+ "rootDir": "src",
+ "outDir": "lib"
+ },
+ "include": ["src/client", "src/*.d.ts"],
+ "exclude": ["**/__tests__/**"]
+}
diff --git a/packages/docusaurus-plugin-content-blog/tsconfig.json b/packages/docusaurus-plugin-content-blog/tsconfig.json
index e16d5c2c5d33..3936df64b7e4 100644
--- a/packages/docusaurus-plugin-content-blog/tsconfig.json
+++ b/packages/docusaurus-plugin-content-blog/tsconfig.json
@@ -1,5 +1,6 @@
{
"extends": "../../tsconfig.json",
+ "references": [{"path": "./tsconfig.client.json"}],
"compilerOptions": {
"noEmit": false,
"incremental": true,
@@ -8,5 +9,5 @@
"outDir": "lib"
},
"include": ["src"],
- "exclude": ["**/__tests__/**"]
+ "exclude": ["src/client", "**/__tests__/**"]
}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogLayout/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogLayout/index.tsx
index 60f9b5e2833f..45dbbb2d2546 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogLayout/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogLayout/index.tsx
@@ -25,9 +25,7 @@ export default function BlogLayout(props: Props): JSX.Element {
className={clsx('col', {
'col--7': hasSidebar,
'col--9 col--offset-1': !hasSidebar,
- })}
- itemScope
- itemType="https://schema.org/Blog">
+ })}>
{children}
{toc &&
{toc}
}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogListPage/StructuredData/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogListPage/StructuredData/index.tsx
new file mode 100644
index 000000000000..a4f808091d82
--- /dev/null
+++ b/packages/docusaurus-theme-classic/src/theme/BlogListPage/StructuredData/index.tsx
@@ -0,0 +1,22 @@
+/**
+ * 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 React from 'react';
+import Head from '@docusaurus/Head';
+import {useBlogListPageStructuredData} from '@docusaurus/theme-common';
+import type {Props} from '@theme/BlogListPage/StructuredData';
+
+export default function BlogListPageStructuredData(props: Props): JSX.Element {
+ const structuredData = useBlogListPageStructuredData(props);
+ return (
+
+
+
+ );
+}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogListPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogListPage/index.tsx
index 4bb30e8cbf40..563327a8a2a2 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogListPage/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogListPage/index.tsx
@@ -19,6 +19,7 @@ import BlogListPaginator from '@theme/BlogListPaginator';
import SearchMetadata from '@theme/SearchMetadata';
import type {Props} from '@theme/BlogListPage';
import BlogPostItems from '@theme/BlogPostItems';
+import BlogListPageStructuredData from '@theme/BlogListPage/StructuredData';
function BlogListPageMetadata(props: Props): JSX.Element {
const {metadata} = props;
@@ -54,6 +55,7 @@ export default function BlogListPage(props: Props): JSX.Element {
ThemeClassNames.page.blogListPage,
)}>
+
);
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Container/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Container/index.tsx
index 05c12d3345ca..5a4fb04e273c 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Container/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Container/index.tsx
@@ -6,36 +6,11 @@
*/
import React from 'react';
-import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
-import {useBlogPost} from '@docusaurus/theme-common/internal';
import type {Props} from '@theme/BlogPostItem/Container';
export default function BlogPostItemContainer({
children,
className,
}: Props): JSX.Element {
- const {
- frontMatter,
- assets,
- metadata: {description},
- } = useBlogPost();
- const {withBaseUrl} = useBaseUrlUtils();
- const image = assets.image ?? frontMatter.image;
- const keywords = frontMatter.keywords ?? [];
- return (
-
- {description && }
- {image && (
-
- )}
- {keywords.length > 0 && (
-
- )}
- {children}
-
- );
+ return {children};
}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Content/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Content/index.tsx
index 592df27d24f6..ebbae6884e67 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Content/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Content/index.tsx
@@ -21,8 +21,7 @@ export default function BlogPostItemContent({
+ className={clsx('markdown', className)}>
{children}
);
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Author/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Author/index.tsx
index 5f2eb1d7be38..5d9935febb04 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Author/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Author/index.tsx
@@ -28,31 +28,18 @@ export default function BlogPostItemHeaderAuthor({
{imageURL && (
-
+
)}
{name && (
-
+
-
- {name}
+
+ {name}
- {title && (
-
- {title}
-
- )}
+ {title &&
{title}}
)}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Info/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Info/index.tsx
index 0775884f60de..22811b499ecc 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Info/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Info/index.tsx
@@ -40,11 +40,7 @@ function ReadingTime({readingTime}: {readingTime: number}) {
}
function Date({date, formattedDate}: {date: string; formattedDate: string}) {
- return (
-
- );
+ return
;
}
function Spacer() {
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Title/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Title/index.tsx
index ea40c2ec752f..1a6ed4a17253 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Title/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostItem/Header/Title/index.tsx
@@ -20,14 +20,8 @@ export default function BlogPostItemHeaderTitle({
const {permalink, title} = metadata;
const TitleHeading = isBlogPostPage ? 'h1' : 'h2';
return (
-
- {isBlogPostPage ? (
- title
- ) : (
-
- {title}
-
- )}
+
+ {isBlogPostPage ? title : {title}}
);
}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/StructuredData/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/StructuredData/index.tsx
new file mode 100644
index 000000000000..72a15a5d2d22
--- /dev/null
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/StructuredData/index.tsx
@@ -0,0 +1,21 @@
+/**
+ * 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 React from 'react';
+import Head from '@docusaurus/Head';
+import {useBlogPostStructuredData} from '@docusaurus/theme-common';
+
+export default function BlogPostStructuredData(): JSX.Element {
+ const structuredData = useBlogPostStructuredData();
+ return (
+
+
+
+ );
+}
diff --git a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx
index f640f603347b..6d7ed51a7fd5 100644
--- a/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/BlogPostPage/index.tsx
@@ -13,6 +13,7 @@ import BlogLayout from '@theme/BlogLayout';
import BlogPostItem from '@theme/BlogPostItem';
import BlogPostPaginator from '@theme/BlogPostPaginator';
import BlogPostPageMetadata from '@theme/BlogPostPage/Metadata';
+import BlogPostPageStructuredData from '@theme/BlogPostPage/StructuredData';
import TOC from '@theme/TOC';
import type {Props} from '@theme/BlogPostPage';
import Unlisted from '@theme/Unlisted';
@@ -45,6 +46,7 @@ function BlogPostPageContent({
) : undefined
}>
{unlisted && }
+
{children}
{(nextItem || prevItem) && (
@@ -64,6 +66,7 @@ export default function BlogPostPage(props: Props): JSX.Element {
ThemeClassNames.page.blogPostPage,
)}>
+
diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json
index 6c439ebab211..7e6effa0abb8 100644
--- a/packages/docusaurus-theme-common/package.json
+++ b/packages/docusaurus-theme-common/package.json
@@ -50,7 +50,8 @@
"@docusaurus/core": "3.0.0",
"@docusaurus/types": "3.0.0",
"fs-extra": "^11.1.1",
- "lodash": "^4.17.21"
+ "lodash": "^4.17.21",
+ "schema-dts": "^1.1.2"
},
"peerDependencies": {
"react": "^18.0.0",
diff --git a/packages/docusaurus-theme-common/src/index.ts b/packages/docusaurus-theme-common/src/index.ts
index 9dfbf59bc81c..b39a078c1bc0 100644
--- a/packages/docusaurus-theme-common/src/index.ts
+++ b/packages/docusaurus-theme-common/src/index.ts
@@ -39,6 +39,11 @@ export {
filterDocCardListItems,
} from './utils/docsUtils';
+export {
+ useBlogListPageStructuredData,
+ useBlogPostStructuredData,
+} from './utils/structuredDataUtils';
+
export {usePluralForm} from './utils/usePluralForm';
export {useCollapsible, Collapsible} from './components/Collapsible';
diff --git a/packages/docusaurus-theme-common/src/utils/structuredDataUtils.ts b/packages/docusaurus-theme-common/src/utils/structuredDataUtils.ts
new file mode 100644
index 000000000000..eb8cea1ad1b3
--- /dev/null
+++ b/packages/docusaurus-theme-common/src/utils/structuredDataUtils.ts
@@ -0,0 +1,169 @@
+/**
+ * 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 {useBaseUrlUtils, type BaseUrlUtils} from '@docusaurus/useBaseUrl';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import {useBlogMetadata} from '@docusaurus/plugin-content-blog/client';
+import type {Props as BlogListPageStructuredDataProps} from '@theme/BlogListPage/StructuredData';
+import {useBlogPost} from '../contexts/blogPost';
+import type {
+ Blog,
+ BlogPosting,
+ WithContext,
+ Person,
+ ImageObject,
+} from 'schema-dts';
+import type {
+ Author,
+ PropBlogPostContent,
+} from '@docusaurus/plugin-content-blog';
+import type {DocusaurusConfig} from '@docusaurus/types';
+
+function getBlogPost(
+ blogPostContent: PropBlogPostContent,
+ siteConfig: DocusaurusConfig,
+ withBaseUrl: BaseUrlUtils['withBaseUrl'],
+) {
+ const {assets, frontMatter, metadata} = blogPostContent;
+ const {date, title, description} = metadata;
+
+ const image = assets.image ?? frontMatter.image;
+ const keywords = frontMatter.keywords ?? [];
+
+ const blogUrl = `${siteConfig.url}${metadata.permalink}`;
+
+ return {
+ '@type': 'BlogPosting',
+ '@id': blogUrl,
+ mainEntityOfPage: blogUrl,
+ url: blogUrl,
+ headline: title,
+ name: title,
+ description,
+ datePublished: date,
+ ...getAuthor(metadata.authors),
+ ...getImage(image, withBaseUrl, title),
+ ...(keywords ? {keywords} : {}),
+ };
+}
+
+function getAuthor(authors: Author[]) {
+ const authorsStructuredData = authors.map(createPersonStructuredData);
+ return {
+ author:
+ authorsStructuredData.length === 1
+ ? authorsStructuredData[0]
+ : authorsStructuredData,
+ };
+}
+
+function getImage(
+ image: string | undefined,
+ withBaseUrl: BaseUrlUtils['withBaseUrl'],
+ title: string,
+) {
+ return image
+ ? {
+ image: createImageStructuredData({
+ imageUrl: withBaseUrl(image, {absolute: true}),
+ caption: `title image for the blog post: ${title}`,
+ }),
+ }
+ : {};
+}
+
+export function useBlogListPageStructuredData(
+ props: BlogListPageStructuredDataProps,
+): WithContext {
+ const {siteConfig} = useDocusaurusContext();
+ const {withBaseUrl} = useBaseUrlUtils();
+
+ const {
+ metadata: {blogDescription, blogTitle, permalink},
+ } = props;
+
+ const url = `${siteConfig.url}${permalink}`;
+
+ // details on structured data support: https://schema.org/Blog
+ return {
+ '@context': 'https://schema.org',
+ '@type': 'Blog',
+ '@id': url,
+ mainEntityOfPage: url,
+ headline: blogTitle,
+ description: blogDescription,
+ blogPost: props.items.map((blogItem) =>
+ getBlogPost(blogItem.content, siteConfig, withBaseUrl),
+ ),
+ };
+}
+
+export function useBlogPostStructuredData(): WithContext {
+ const blogMetadata = useBlogMetadata();
+ const {assets, metadata} = useBlogPost();
+ const {siteConfig} = useDocusaurusContext();
+ const {withBaseUrl} = useBaseUrlUtils();
+
+ const {date, title, description, frontMatter} = metadata;
+
+ const image = assets.image ?? frontMatter.image;
+ const keywords = frontMatter.keywords ?? [];
+
+ const url = `${siteConfig.url}${metadata.permalink}`;
+
+ // details on structured data support: https://schema.org/BlogPosting
+ // BlogPosting is one of the structured data types that Google explicitly
+ // supports: https://developers.google.com/search/docs/appearance/structured-data/article#structured-data-type-definitions
+ return {
+ '@context': 'https://schema.org',
+ '@type': 'BlogPosting',
+ '@id': url,
+ mainEntityOfPage: url,
+ url,
+ headline: title,
+ name: title,
+ description,
+ datePublished: date,
+ ...getAuthor(metadata.authors),
+ ...getImage(image, withBaseUrl, title),
+ ...(keywords ? {keywords} : {}),
+ isPartOf: {
+ '@type': 'Blog',
+ '@id': `${siteConfig.url}${blogMetadata.blogBasePath}`,
+ name: blogMetadata.blogTitle,
+ },
+ };
+}
+
+/** @returns A {@link https://schema.org/Person} constructed from the {@link Author} */
+function createPersonStructuredData(author: Author): Person {
+ return {
+ '@type': 'Person',
+ ...(author.name ? {name: author.name} : {}),
+ ...(author.title ? {description: author.title} : {}),
+ ...(author.url ? {url: author.url} : {}),
+ ...(author.email ? {email: author.email} : {}),
+ ...(author.imageURL ? {image: author.imageURL} : {}),
+ };
+}
+
+/** @returns A {@link https://schema.org/ImageObject} */
+function createImageStructuredData({
+ imageUrl,
+ caption,
+}: {
+ imageUrl: string;
+ caption: string;
+}): ImageObject {
+ return {
+ '@type': 'ImageObject',
+ '@id': imageUrl,
+ url: imageUrl,
+ contentUrl: imageUrl,
+ caption,
+ };
+}
diff --git a/packages/docusaurus-types/src/routing.d.ts b/packages/docusaurus-types/src/routing.d.ts
index 3e2ae2ab0bbd..aff344d52472 100644
--- a/packages/docusaurus-types/src/routing.d.ts
+++ b/packages/docusaurus-types/src/routing.d.ts
@@ -75,7 +75,7 @@ export type RouteContext = {
/**
* Plugin-specific context data.
*/
- data?: object | undefined;
+ data?: {[key: string]: unknown};
};
/**
diff --git a/website/docs/seo.mdx b/website/docs/seo.mdx
index 031ab1ddf340..5d8f6d56ed40 100644
--- a/website/docs/seo.mdx
+++ b/website/docs/seo.mdx
@@ -60,7 +60,7 @@ To read more about types of meta tags, visit [the MDN docs](https://developer.mo
Similar to [global metadata](#global-metadata), Docusaurus also allows for the addition of meta-information to individual pages. Follow [this guide](./guides/markdown-features/markdown-features-head-metadata.mdx) for configuring the `` tag. In short:
-```md title="my-markdown-page.md"
+```md title="my-markdown-page.mdx"
# A cooking guide
diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts
index 6599b6fb0744..0d5127874378 100644
--- a/website/docusaurus.config.ts
+++ b/website/docusaurus.config.ts
@@ -453,6 +453,8 @@ export default async function createConfigAsync() {
type: 'all',
copyright: `Copyright © ${new Date().getFullYear()} Facebook, Inc.`,
},
+ blogTitle: 'Docusaurus blog',
+ blogDescription: 'Read blog posts about Docusaurus from the team',
blogSidebarCount: 'ALL',
blogSidebarTitle: 'All our posts',
} satisfies BlogOptions,
diff --git a/yarn.lock b/yarn.lock
index e44765c458bd..54c8fb7ce9bc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -14539,6 +14539,11 @@ scheduler@^0.23.0:
dependencies:
loose-envify "^1.1.0"
+schema-dts@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/schema-dts/-/schema-dts-1.1.2.tgz#82ccf71b5dcb80065a1cc5941888507a4ce1e44b"
+ integrity sha512-MpNwH0dZJHinVxk9bT8XUdjKTxMYrA5bLtrrGmFA6PTLwlOKnhi67XoRd6/ty+Djt6ZC0slR57qFhZDNMI6DhQ==
+
schema-utils@2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7"