From 46276c98f9f00c481eba96c52722164556383694 Mon Sep 17 00:00:00 2001 From: longsizhuo Date: Thu, 16 Apr 2026 19:02:59 +0000 Subject: [PATCH] =?UTF-8?q?feat(seo):=20=E5=85=A8=E7=AB=99=20SEO=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=20=E2=80=94=20sitemap=20/=20JSON-LD=20/=20ca?= =?UTF-8?q?nonical=20/=20robots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **新增结构化数据(JSON-LD):** - 全局 WebSite + SearchAction(让 Google 搜索结果下方可能显示站内搜索框) - docs 页 TechArticle + BreadcrumbList(技术文章 rich result + 面包屑层级) - /u/[username] 页 Person(个人档案 knowledge panel 候选) **sitemap 扩容(从仅首页+docs → 312 条):** - 新增 /rank 条目(changeFreq=daily) - 新增 /u/{githubId} 条目(枚举 leaderboard JSON 全部贡献者,非贡献者 profile 不入 sitemap 节省 crawl budget) **canonical + hreflang:** - docs [...slug] 页:canonical 指向 slug 原路径;alternates.languages 声明 zh-CN / en-US / x-default - /u/[username]:canonical 用 githubId 数字路径,避免 github_ 和数字两种 URL 竞争 PageRank - /rank、/login、/settings 各加 canonical **robots 调整:** - 删 nocache: true(反而抑制 rich snippet) - googleBot 上放开 max-image-preview=large / max-snippet=-1 让 Google 自行决定摘要长度 - /login、/settings 设 index=false(登录/偏好页不需搜索引擎收录) **per-page metadata:** - /rank 加 title / description / OG - /u/[username] OG 从全局 og/cover.png 覆盖为用户 avatarUrl - docs 页 OG 加 type=article + locale 跟随 --- app/docs/[...slug]/page.tsx | 78 +++++++++++++++++++++++++++++++++++++ app/layout.tsx | 36 +++++++++++++++-- app/login/page.tsx | 9 +++++ app/rank/page.tsx | 16 ++++++++ app/settings/page.tsx | 9 +++++ app/sitemap.ts | 27 ++++++++++++- app/u/[username]/page.tsx | 61 +++++++++++++++++++++++++---- 7 files changed, 223 insertions(+), 13 deletions(-) diff --git a/app/docs/[...slug]/page.tsx b/app/docs/[...slug]/page.tsx index 3f251721..45dba950 100644 --- a/app/docs/[...slug]/page.tsx +++ b/app/docs/[...slug]/page.tsx @@ -93,8 +93,59 @@ export default async function DocPage({ params }: Param) { getDocContributorsByDocId(docIdFromPage); const Mdx = page.data.body; + // SEO 结构化数据 + const siteUrl = + process.env.NEXT_PUBLIC_SITE_URL || "https://involutionhell.com"; + const slugPath = (slug ?? []).join("/"); + const docUrl = slugPath ? `${siteUrl}/docs/${slugPath}` : `${siteUrl}/docs`; + + // TechArticle: 让 docs 在 Google 搜索结果上更可能展示为技术文章卡片 + const articleJsonLd = { + "@context": "https://schema.org", + "@type": "TechArticle", + headline: page.data.title, + description: page.data.description, + url: docUrl, + inLanguage: locale === "en" ? "en-US" : "zh-CN", + publisher: { + "@type": "Organization", + name: "Involution Hell", + url: siteUrl, + }, + }; + + // BreadcrumbList: 按 slug 层级生成面包屑(Google 搜索结果里的那种层级链接) + const breadcrumbItems = [ + { name: "Involution Hell", url: siteUrl }, + { name: "Docs", url: `${siteUrl}/docs` }, + ...(slug ?? []).map((seg, idx) => ({ + name: decodeURIComponent(seg), + url: `${siteUrl}/docs/${slug!.slice(0, idx + 1).join("/")}`, + })), + ]; + const breadcrumbJsonLd = { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: breadcrumbItems.map((item, idx) => ({ + "@type": "ListItem", + position: idx + 1, + name: item.name, + item: item.url, + })), + }; + return ( <> +