fix(docs): align SEO metadata with page content
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
This commit is contained in:
committed by
Junior Garcia
parent
56f2278c25
commit
2e65a8b5a9
@@ -26,6 +26,7 @@ import {PRContributors, fetchPRContributors} from "@/components/pr-contributors"
|
||||
import StatusChip from "@/components/status-chip";
|
||||
import {siteConfig} from "@/config/site";
|
||||
import {getComponentCount, getExampleCount} from "@/demos";
|
||||
import {getDocsSeoMetadata} from "@/lib/docs-seo";
|
||||
import {getBreadcrumbJsonLd, getTechArticleJsonLd} from "@/lib/json-ld";
|
||||
import {absoluteUrl, getLocalizedAlternates, localizedPath, stripLocale} from "@/lib/seo";
|
||||
import {source} from "@/lib/source";
|
||||
@@ -38,28 +39,6 @@ import {
|
||||
// import { getGithubLastEdit } from "fumadocs-core/server";
|
||||
|
||||
const componentStatusIcons = ["preview", "new", "updated"];
|
||||
const ENGLISH_SEO_OVERRIDES: Record<string, {description: string; title: string}> = {
|
||||
"/docs/react/components": {
|
||||
description:
|
||||
"Browse accessible HeroUI React components for forms, overlays, navigation, data display, and more, built with React Aria and Tailwind CSS v4.",
|
||||
title: "HeroUI React Components – Accessible UI Library",
|
||||
},
|
||||
"/docs/react/components/button": {
|
||||
description:
|
||||
"Build accessible React buttons with HeroUI. Explore variants, sizes, loading and disabled states, icon buttons, events, and ButtonGroup patterns.",
|
||||
title: "HeroUI Button – Accessible React Button Component",
|
||||
},
|
||||
"/docs/react/components/select": {
|
||||
description:
|
||||
"Build accessible React select menus with HeroUI. Learn options, sections, validation, disabled states, controlled values, and customizable listboxes.",
|
||||
title: "HeroUI Select – Accessible React Select Component",
|
||||
},
|
||||
"/docs/react/getting-started": {
|
||||
description:
|
||||
"Get started with HeroUI v3, an accessible React UI library built on React Aria and Tailwind CSS v4. Learn installation, principles, and customization.",
|
||||
title: "HeroUI v3 – React UI Library Getting Started",
|
||||
},
|
||||
};
|
||||
|
||||
const getRawMDXContent = cache(async (pagePath: string): Promise<string> => {
|
||||
try {
|
||||
@@ -111,6 +90,7 @@ export default async function Page(props: {params: Promise<{lang: string; slug?:
|
||||
const slugParts = params.slug ?? [];
|
||||
const pagePath = `/docs/${slugParts.join("/")}`;
|
||||
const pageUrl = absoluteUrl(localizedPath(params.lang, pagePath));
|
||||
const seoMetadata = getDocsSeoMetadata(params.lang, pagePath);
|
||||
|
||||
const breadcrumbItems = [
|
||||
{name: "Home", url: absoluteUrl(localizedPath(params.lang))},
|
||||
@@ -132,8 +112,8 @@ export default async function Page(props: {params: Promise<{lang: string; slug?:
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(
|
||||
getTechArticleJsonLd({
|
||||
description: page.data.description ?? "",
|
||||
title: page.data.title,
|
||||
description: seoMetadata?.description ?? page.data.description ?? "",
|
||||
title: seoMetadata?.title ?? page.data.title,
|
||||
url: pageUrl,
|
||||
}),
|
||||
),
|
||||
@@ -219,7 +199,7 @@ export async function generateMetadata(props: {
|
||||
const url = page.url;
|
||||
const unlocalizedPath = stripLocale(url);
|
||||
const alternates = getLocalizedAlternates({locale: params.lang, path: unlocalizedPath});
|
||||
const seoOverride = params.lang === "en" ? ENGLISH_SEO_OVERRIDES[unlocalizedPath] : undefined;
|
||||
const seoOverride = getDocsSeoMetadata(params.lang, unlocalizedPath);
|
||||
const description = seoOverride?.description ?? page.data.description;
|
||||
const title = seoOverride?.title ?? page.data.title;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ export default async function ThemeBuilderPage({params}: {params: Promise<{lang:
|
||||
className="grid h-dvh grid-rows-[auto_1fr_auto] bg-background px-4 sm:overflow-hidden sm:px-6"
|
||||
id={THEME_BUILDER_PAGE_ID}
|
||||
>
|
||||
<h1 className="sr-only">{dict.themes.metaTitle}</h1>
|
||||
<h1 className="sr-only">{dict.themes.heading}</h1>
|
||||
<BuilderHeader />
|
||||
<ThemeBuilderContent />
|
||||
<div className="mx-auto hidden items-center justify-between gap-4 py-6 max-[1200px]:flex-col sm:flex">
|
||||
|
||||
@@ -8,6 +8,8 @@ import {notFound} from "next/navigation";
|
||||
import {ImageResponse} from "next/og";
|
||||
|
||||
import {HeroUILogo} from "@/components/heroui-logo";
|
||||
import {getDocsSeoMetadata} from "@/lib/docs-seo";
|
||||
import {stripLocale} from "@/lib/seo";
|
||||
import {source} from "@/lib/source";
|
||||
|
||||
interface GenerateProps {
|
||||
@@ -93,8 +95,10 @@ export const GET = async (_req: Request, {params}: {params: Promise<{slug: strin
|
||||
|
||||
if (!page) notFound();
|
||||
|
||||
const seoMetadata = getDocsSeoMetadata(page.locale, stripLocale(page.url));
|
||||
|
||||
return generateOGImage({
|
||||
description: page.data.description,
|
||||
description: seoMetadata?.description ?? page.data.description,
|
||||
fonts: [
|
||||
{
|
||||
data: interRegular,
|
||||
@@ -108,7 +112,7 @@ export const GET = async (_req: Request, {params}: {params: Promise<{slug: strin
|
||||
},
|
||||
],
|
||||
icon: <HeroUILogo size={58} />,
|
||||
title: page.data.title,
|
||||
title: seoMetadata?.title ?? page.data.title,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -117,8 +117,9 @@
|
||||
"androidComingSoon": "Android · 即将推出"
|
||||
},
|
||||
"themes": {
|
||||
"heading": "主题编辑器",
|
||||
"metaTitle": "HeroUI 主题编辑器 – 自定义 React UI",
|
||||
"metaDescription": "通过可视化控件自定义 HeroUI React 主题,调整颜色、字体与圆角,实时预览组件并复制可用于生产环境的 Tailwind CSS v4 变量。",
|
||||
"metaDescription": "通过可视化控件自定义 HeroUI React 主题,调整颜色、字体与圆角,实时预览组件并复制可用于生产环境的 HeroUI CSS 变量。",
|
||||
"theme": "主题",
|
||||
"custom": "自定义",
|
||||
"designTheme": "设计主题",
|
||||
|
||||
@@ -117,8 +117,9 @@
|
||||
"androidComingSoon": "Android · Coming soon"
|
||||
},
|
||||
"themes": {
|
||||
"heading": "Theme Builder",
|
||||
"metaTitle": "HeroUI Theme Builder – Customize React UI",
|
||||
"metaDescription": "Customize HeroUI React themes visually. Tune colors, typography, and radius, preview components live, and copy production-ready Tailwind CSS v4 variables.",
|
||||
"metaDescription": "Customize HeroUI React themes visually. Tune colors, typography, and radius, preview components live, and copy production-ready HeroUI CSS variables.",
|
||||
"theme": "Theme",
|
||||
"custom": "Custom",
|
||||
"designTheme": "Design theme",
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
export interface DocsSeoMetadata {
|
||||
description: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
const ENGLISH_DOCS_SEO_METADATA: Readonly<Record<string, DocsSeoMetadata>> = {
|
||||
"/docs/react/components": {
|
||||
description:
|
||||
"Browse accessible HeroUI React components for forms, overlays, navigation, data display, and more, built with React Aria and Tailwind CSS v4.",
|
||||
title: "HeroUI React Components – Accessible UI Library",
|
||||
},
|
||||
"/docs/react/components/button": {
|
||||
description:
|
||||
"Build accessible React buttons with HeroUI. Explore variants, sizes, icon-only states, custom styles, ripple effects, render props, and BEM classes.",
|
||||
title: "HeroUI Button – Accessible React Button Component",
|
||||
},
|
||||
"/docs/react/components/select": {
|
||||
description:
|
||||
"Build accessible React select inputs with HeroUI. Explore single and multiple selection, async loading, sections, disabled items, and controlled values.",
|
||||
title: "HeroUI Select – Accessible React Select Component",
|
||||
},
|
||||
"/docs/react/getting-started": {
|
||||
description:
|
||||
"Meet HeroUI v3, an accessible React UI library built on React Aria and Tailwind CSS v4. Explore its design approach, ecosystem, and common questions.",
|
||||
title: "Introduction to HeroUI v3 – React UI Library",
|
||||
},
|
||||
};
|
||||
|
||||
export function getDocsSeoMetadata(
|
||||
locale: string | undefined,
|
||||
unlocalizedPath: string,
|
||||
): DocsSeoMetadata | undefined {
|
||||
return locale === "en" ? ENGLISH_DOCS_SEO_METADATA[unlocalizedPath] : undefined;
|
||||
}
|
||||
@@ -65,7 +65,7 @@ node scripts/get_hooks_migration_guide.mjs
|
||||
|
||||
### Direct URLs
|
||||
|
||||
Migration docs (preview): `https://heroui-git-docs-migration-heroui.vercel.app/docs/react/migration/{filename}`
|
||||
Migration docs (preview): use a concrete guide URL from the examples below, and never fetch a URL that still contains a placeholder.
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
@@ -76,8 +76,7 @@ node scripts/get_docs.mjs /docs/native/getting-started/theming
|
||||
|
||||
### Direct MDX URLs
|
||||
|
||||
Use a concrete kebab-case component slug in every MDX request. Never request an unresolved
|
||||
template URL.
|
||||
Component docs: fetch `.mdx` with a concrete kebab-case slug. Run `node scripts/list_components.mjs` when the slug is unknown, and never fetch a URL that still contains a placeholder.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -85,8 +84,7 @@ Examples:
|
||||
- Dialog: `https://heroui.com/docs/native/components/dialog.mdx`
|
||||
- TextField: `https://heroui.com/docs/native/components/text-field.mdx`
|
||||
|
||||
For getting-started guides, use a concrete topic URL such as
|
||||
`https://heroui.com/docs/native/getting-started/quick-start.mdx`.
|
||||
Getting started guides: use a concrete topic URL such as `https://heroui.com/docs/native/getting-started/quick-start.mdx`.
|
||||
|
||||
**Important:** Always fetch component docs before implementing. The MDX docs include complete examples, props, anatomy, and API references.
|
||||
|
||||
|
||||
@@ -98,8 +98,7 @@ node scripts/get_docs.mjs /docs/react/getting-started/theming
|
||||
|
||||
### Direct MDX URLs
|
||||
|
||||
Use a concrete kebab-case component slug in every MDX request. Never request an unresolved
|
||||
template URL.
|
||||
Component docs: fetch `.mdx` with a concrete kebab-case slug. Run `node scripts/list_components.mjs` when the slug is unknown, and never fetch a URL that still contains a placeholder.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -107,8 +106,7 @@ Examples:
|
||||
- Modal: `https://heroui.com/docs/react/components/modal.mdx`
|
||||
- Form: `https://heroui.com/docs/react/components/form.mdx`
|
||||
|
||||
For getting-started guides, use a concrete topic URL such as
|
||||
`https://heroui.com/docs/react/getting-started/quick-start.mdx`.
|
||||
Getting started guides: use a concrete topic URL such as `https://heroui.com/docs/react/getting-started/quick-start.mdx`.
|
||||
|
||||
**Important:** Always fetch component docs before implementing. The MDX docs include complete examples, props, anatomy, and API references.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user