Skip to content

Commit 329795f

Browse files
committed
fix(docs): add SEO-optimized page titles
- Add generateMetadata function to generate page-specific titles - Extract title from MDX metadata or generate from path - Ensure title length follows SEO best practices (50-60 chars) - Fix duplicate site name in title by using layout template - Add OpenGraph metadata for better social sharing Signed-off-by: ryjiang <jiangruiyi@gmail.com>
1 parent c6e08dd commit 329795f

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

docs/app/[[...mdxPath]]/page.jsx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,84 @@ export async function generateStaticParams() {
4242
}));
4343
}
4444

45+
export async function generateMetadata(props) {
46+
const params = await props.params;
47+
const mdxPath = params?.mdxPath || [];
48+
const pathSegments = Array.isArray(mdxPath) ? mdxPath : [];
49+
50+
try {
51+
const result = await importPage(pathSegments, '');
52+
if (!result || !result.metadata) {
53+
return {
54+
title: 'Milvus Node.js SDK',
55+
description: 'The official Milvus client for Node.js',
56+
};
57+
}
58+
59+
const { metadata } = result;
60+
const siteName = 'Milvus Node.js SDK';
61+
const templateSuffix = ' | Milvus Node.js SDK';
62+
const maxTotalTitleLength = 60;
63+
const maxPageTitleLength = maxTotalTitleLength - templateSuffix.length;
64+
const maxDescriptionLength = 160;
65+
66+
// Extract title from metadata (nextra extracts from first h1)
67+
let pageTitle = metadata.title || '';
68+
69+
// If no title, try to generate from path
70+
if (!pageTitle && pathSegments.length > 0) {
71+
const lastSegment = pathSegments[pathSegments.length - 1];
72+
pageTitle = lastSegment
73+
.split('-')
74+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
75+
.join(' ');
76+
}
77+
78+
// If still no title, use default
79+
if (!pageTitle) {
80+
pageTitle = 'Documentation';
81+
}
82+
83+
// SEO best practices: total title should be 50-60 characters
84+
// Layout already has template '%s | Milvus Node.js SDK', so we only return page title
85+
// Truncate page title if needed to ensure total length stays within limit
86+
if (pageTitle.length > maxPageTitleLength) {
87+
pageTitle = pageTitle.substring(0, maxPageTitleLength - 3) + '...';
88+
}
89+
90+
// Full title for OpenGraph (without template, we construct it manually)
91+
const fullTitle = `${pageTitle}${templateSuffix}`;
92+
93+
// Extract description from metadata or use default
94+
let description =
95+
metadata.description ||
96+
metadata.frontMatter?.description ||
97+
'The official Milvus client for Node.js';
98+
99+
// Truncate description if too long
100+
if (description.length > maxDescriptionLength) {
101+
description = description.substring(0, maxDescriptionLength - 3) + '...';
102+
}
103+
104+
return {
105+
title: pageTitle,
106+
description,
107+
openGraph: {
108+
title: fullTitle,
109+
description,
110+
type: 'website',
111+
siteName: siteName,
112+
},
113+
};
114+
} catch (error) {
115+
console.error('Error generating metadata:', error);
116+
return {
117+
title: 'Milvus Node.js SDK',
118+
description: 'The official Milvus client for Node.js',
119+
};
120+
}
121+
}
122+
45123
export default async function Page(props) {
46124
const params = await props.params;
47125
const mdxPath = params?.mdxPath || [];

0 commit comments

Comments
 (0)