mirror of
https://github.com/vercel/chat.git
synced 2026-09-14 18:32:29 +08:00
927d0dbd7d
Many docs pages are orphaned: nothing links to them apart from the sidebar, so readers and crawlers rarely find them. This PR gives every docs page a Read more section with four cards at the bottom of the article, above the prev/next footer. Cards are picked deterministically in lib/read-more.ts: the page's related frontmatter first, then prerequisites, then siblings from the same sidebar section, then the rest of the page tree, so every page always fills all four slots. Card titles and descriptions come from the target page's own frontmatter, nothing is duplicated. The section is injected through the MDX wrapper slot in the docs route, so it applies to all pages without touching content. To make the links topical rather than positional, 26 pages get related frontmatter additions. The 20 pages that no other page referenced (all ten api/ pages among them) now each have at least one inbound link, generally pairing guides with their API reference and back. The bundled copy of create-chat-sdk.mdx is synced to keep the byte-match test green. Official adapter pages get the same treatment with a More adapters section: same-type adapters first (platform or state, using the catalog order), topped up from the other official group. Vendor-official and community adapters are never shown, and their pages don't render the section. It reuses AdapterCard, so logos and package names match the listing page. Two small SEO fixes ride along. JSON-LD was allowlisted to three docs pages; the allowlist is gone, so all 45 now emit HowTo or TechArticle plus a BreadcrumbList. Docs and adapter detail pages also emit canonical URLs now, resolved against the existing metadataBase. Verified against the production build: all 45 docs pages and all 19 official adapter pages render exactly four cards, no page is left unreferenced, canonicals and JSON-LD are present everywhere, and pnpm validate passes. Docs-only, so no changeset. --------- Signed-off-by: Ben Sabic <bensabic@users.noreply.github.com> Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
111 lines
2.7 KiB
TypeScript
111 lines
2.7 KiB
TypeScript
import type { TableOfContents } from "fumadocs-core/toc";
|
|
|
|
const BASE_URL = "https://chat-sdk.dev";
|
|
|
|
const VERCEL_ORG = {
|
|
"@type": "Organization",
|
|
name: "Vercel",
|
|
url: "https://vercel.com",
|
|
};
|
|
|
|
interface DocsPage {
|
|
data: {
|
|
description?: string;
|
|
title?: string;
|
|
toc?: TableOfContents;
|
|
type?: string;
|
|
};
|
|
url: string;
|
|
}
|
|
|
|
const getDocsPageUrl = (pageUrl: string) =>
|
|
pageUrl.startsWith("http") ? pageUrl : `${BASE_URL}${pageUrl}`;
|
|
|
|
const getDocsBreadcrumb = (title: string, pageUrl: string) => ({
|
|
"@context": "https://schema.org",
|
|
"@type": "BreadcrumbList",
|
|
itemListElement: [
|
|
{ "@type": "ListItem", position: 1, name: "Chat SDK", item: BASE_URL },
|
|
{
|
|
"@type": "ListItem",
|
|
position: 2,
|
|
name: "Documentation",
|
|
item: `${BASE_URL}/docs`,
|
|
},
|
|
{ "@type": "ListItem", position: 3, name: title, item: pageUrl },
|
|
],
|
|
});
|
|
|
|
const getStepNameFromTocEntry = (entry: {
|
|
title: TableOfContents[number]["title"];
|
|
url: string;
|
|
}): string => {
|
|
if (typeof entry.title === "string" && entry.title.length > 0) {
|
|
return entry.title;
|
|
}
|
|
|
|
const hash = entry.url.startsWith("#") ? entry.url.slice(1) : entry.url;
|
|
return hash
|
|
.split("-")
|
|
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|
.join(" ");
|
|
};
|
|
|
|
const getHowToJsonLd = (
|
|
title: string,
|
|
description: string | undefined,
|
|
pageUrl: string,
|
|
toc: DocsPage["data"]["toc"]
|
|
) => {
|
|
const steps = (toc ?? [])
|
|
.filter((entry) => entry.depth === 2)
|
|
.map((entry, index) => ({
|
|
"@type": "HowToStep",
|
|
position: index + 1,
|
|
name: getStepNameFromTocEntry(entry),
|
|
url: `${pageUrl}${entry.url}`,
|
|
}));
|
|
|
|
return {
|
|
"@context": "https://schema.org",
|
|
"@type": "HowTo",
|
|
name: title,
|
|
description,
|
|
url: pageUrl,
|
|
publisher: VERCEL_ORG,
|
|
...(steps.length > 0 ? { step: steps } : {}),
|
|
};
|
|
};
|
|
|
|
const getTechArticleJsonLd = (
|
|
title: string,
|
|
description: string | undefined,
|
|
pageUrl: string
|
|
) => ({
|
|
"@context": "https://schema.org",
|
|
"@type": "TechArticle",
|
|
headline: title,
|
|
description,
|
|
url: pageUrl,
|
|
author: VERCEL_ORG,
|
|
publisher: VERCEL_ORG,
|
|
});
|
|
|
|
/**
|
|
* Build JSON-LD for documentation pages.
|
|
* Guides (`type: guide`) emit `HowTo` with h2 sections as steps; other pages
|
|
* use `TechArticle`. Always includes a `BreadcrumbList`.
|
|
*/
|
|
export const getDocsJsonLd = (page: DocsPage) => {
|
|
const pageUrl = getDocsPageUrl(page.url);
|
|
const { description, type, toc } = page.data;
|
|
const title = page.data.title ?? "Chat SDK";
|
|
const breadcrumb = getDocsBreadcrumb(title, pageUrl);
|
|
|
|
if (type === "guide") {
|
|
return [getHowToJsonLd(title, description, pageUrl, toc), breadcrumb];
|
|
}
|
|
|
|
return [getTechArticleJsonLd(title, description, pageUrl), breadcrumb];
|
|
};
|