Civitai 双域名架构下的 SEO 审计指南:NSFW 内容分级、deIndex 门控与站点地图一致性 📅 发布时间:2026/9/18 21:51:13 👁 浏览次数: Civitai 双域名架构下的 SEO 审计指南NSFW 内容分级、deIndex 门控与站点地图一致性【免费下载链接】civitaiA repository of models, textual inversions, and more项目地址: https://gitcode.com/GitHub_Trending/ci/civitai本文基于仓库内 docs/seo-audit.md 展开系统讲解 Civitai 在「绿域 civitai.com / 红域 civitai.red」双宿主架构下如何审计与治理搜索引擎收录从域名边界处的爬虫行为、Meta组件防线、全局canIndex门控到 P0–P4 分层审计清单、sitemap 一致性与验证工具链。读完你既能掌握一套可复用的「分级内容 SEO 审计」方法论也能直接对照 Civitai 源码理解每一条规则的落地位置。一、背景双域名架构与内容分级Civitai 由同一套代码库驱动两个规范宿主canonical host按内容评级nsfwLevel做物理隔离域名角色收录内容civitai.comgreenSFW 站nsfwLevel通过hasSafeBrowsingLevel的内容civitai.redred / blueNSFW 站全部内容含成人内容域名的判定在服务端完成。src/pages/_app.tsx 中canIndex getAllServerHosts().includes((request.headers.host ?? ).toLowerCase())对应文档所指的_app.tsx域名解析逻辑实际位于第 419 行附近即只要请求 Host 命中规范服务器域名集合就认为「本页可被收录」。该布尔值通过AppProvider注入 React 层_app.tsx第 210 行。客户端拿到域名的方式是特性标志feature flag风格isGreen.comisBlue/isRed.red变体。src/hooks/useDomainColor.tsx 据此返回ColorDomain缺省回退到最安全的greenconst color: ColorDomain features.isGreen ? green : features.isBlue ? blue : features.isRed ? red : blue;ColorDomain的合法取值定义在 src/shared/constants/domain.constants.ts[green, blue, red]每个域名可配置primary规范宿主与aliases入站时解析到同一配色的别名宿主。关键结论索引门控canIndex只看 Host 是否匹配规范域名与内容评级无关。因此.red目前天然处于canIndex: true区域——是否要让红域内容被收录是产品决策而非技术副作用详见下文「未决问题」。二、域名边界处的爬虫行为与「内容/元数据不匹配」当用户在.com绿域请求一个 NSFW 资源时服务端渲染SSR按以下顺序工作SSR 渲染页面本体Meta被渲染在可见性门控组件之外保证 meta 标签永远存在这也是审计清单第一条的由来门控组件内部用一张「Mature content has a new home → civitai.red」替换卡片替代真实正文Googlebot未登录、仅安全级别收到的 HTML 是文章的规范 title description来自 Meta 一个把用户引向站外的正文。于是问题出现了如果该 URL 在.com上仍然可索引就形成正文与元数据不一致content/meta mismatch——SERP 片段描述的是内容而点进去却是跳转卡片。文档给出的标准修复模式是当「处于 green 域名 且 内容为 NSFW」时让deIndex生效输出noindex,nofollow把 canonical 之争让给.redURL。SensitiveShield 的演进Gated文档写作时引用的是SensitiveShield组件而从当前仓库源码看该模式已演进为 src/components/Gated/Gated.tsx 这一「NSFW 门控 Meta 的组合包装器」。组件注释明确说明它取代了先前「Meta与SensitiveShield作为兄弟节点」的写法用于七个实体详情页表面。Gated内置了默认 de-index 判定shouldDefaultDeIndex只要满足以下任一状态即强制 noindex第 188–192 行const shouldDefaultDeIndex state redirect || state login || state unrated || (state page allowMatureContent isSafeForCanonical);并以||而非??合并调用方传入的deIndex避免调用方传入的false掩盖默认值第 204–206 行const finalMeta: MetaPropsTImage { ...meta, deIndex: meta.deIndex || shouldDefaultDeIndex, ... };Gated同时负责付费墙paywall结构化数据的增强当为已验证爬虫渲染时若页面提供了实体 schema则追加isAccessibleForFree: false与hasPart付费墙声明否则输出独立的WebPage付费墙 schema保证cssSelector → DOM契约仍有结构化数据声明。Meta 组件的安全防线src/components/Meta/Meta.tsx 是页头元数据的最终出口内含三层保护图片安全过滤第一道防线og:image只从images中挑选getIsSafeBrowsingLevel(image.nsfwLevel)通过的图片第 81 行并在存在ogEndpoint时优先使用/api/og端点第 87 行——该端点被期望无论内容评级如何都渲染一张 SFW 预览卡。文档特别强调如果未来允许 NSFW 内容走原始图片兜底这个过滤就是最后一道防线绝不能去掉。robots 合成第二道防线(deIndex || !canIndex || hasDialogParam)任一为真即输出meta namerobots contentnoindex,nofollow /第 130–132 行。也就是说即使页面忘了传deIndex只要全局canIndex为假非规范域名爬虫依然拿不到索引放行。canonical / alternate / JSON-LDcanonical与alternate由页面级传入最终拼上NEXT_PUBLIC_BASE_URL输出第 133–134 行schema与breadcrumb各自作为独立 JSON-LD 块输出第 135–148 行面包屑单独成块是为了防止Gated的付费墙增强把实体属性附着到面包屑列表上。职责边界deIndex、canonical、alternate都是页面级控制每个页面负责传入正确的值Meta只负责“守门”与“兜底”不越权替页面做内容判定。三、全局索引门控canIndexcanIndex是_app.tsx在服务端基于 Host 计算的全局布尔值第 419 行经由AppProvider第 210 行暴露给useAppContext()Meta组件内部读取它参与 noindex 合成。要点归纳Host 命中规范服务器域名 →canIndex: true对内容评级完全不敏感.red当前位于canIndex: true区域是否索引.red内容属于产品问题涉及广告网络、安全搜索合规、外链画像不应让「Host 匹配」这一副作用替团队做决定非规范域名的页面如预览环境、镜像别名天然 noindex这是一道免费的全局兜底。四、详情页审计清单逐项检查标准文档为所有详情页models、images、posts、articles、collections、用户主页、bounty、club 等定义了 7 项必查项这是整套审计的方法论核心Meta位于任何可见性门控之外SensitiveShield/ 登录门 / 成人内容模糊层description派生自可安全展示在 SERP 片段的内容若内容为 NSFW 则整页 de-indexog:image使用/api/og或 SFW 过滤选择器绝不使用未过滤的image.urldeIndex在以下任一场景置位内容未发布 / 草稿态availability Unsearchable位于.com且内容为 NSFWcanonical指向带 slug 的生产 URL或明确选择不带 slug 的 URL 作为规范但必须保持一致若无 slug 与带 slug 的 URL 均可解析设置alternateJSON-LD schemaArticle、Product、Person、ImageObject 等在有价值处添加可选。五、分层审计计划P0 → P4文档按风险与流量把全站路由分成五层每页审计通过后在 Findings 中登记即使无问题也登记“no issues”。P0 — 含 NSFW 内容的详情页最高优先级最可能产生「内容/元数据不匹配」全部为用户评级内容全部需要 NSFW 感知的deIndex守卫路由文件/articles/:id/:slug?✅ 已修复 2026-04-24src/pages/articles/[id]/[[...slug]].tsx/models/:id/:slug?src/pages/models/[id]/[[...slug]].tsx/model-versions/:idsrc/pages/model-versions/[id].tsx/images/:imageIdsrc/pages/images/[imageId].tsx/posts/:postId/:postSlug?src/pages/posts/[postId]/[[...postSlug]].tsx/bounties/:id/:slug?src/pages/bounties/[id]/[[...slug]].tsx/bounties/:id/entries/:entryIdsrc/pages/bounties/[id]/entries/[entryId]/index.tsx/collections/:collectionIdsrc/pages/collections/[collectionId]/index.tsx/comics/:id/:slug?src/pages/comics/[id]/[[...slug]].tsxP1 — 聚合/衍生评级的用户页面聚合用户内容meta 中可能浮现 NSFW 预览且对 SEO 可见/user/:username— src/pages/user/[username]/index.tsx/user/:username/models|images|posts|videos|articles|collections|comics— src/pages/user/[username]/models.tsx 等/user/:username/:listcatch-all 列表路由— src/pages/user/[username]/[list].tsx/user-id/:userId— src/pages/user-id/[userId].tsx需确认 canonical 指向 username URL/tag/:tagname标签聚合可能含 NSFW— src/pages/tag/[tagname].tsx/reviews/:reviewId— src/pages/reviews/[reviewId].tsx/comments/v2/:id很可能应 de-index— src/pages/comments/v2/[id].tsx/challenges/:id/:slug?— src/pages/challenges/[id]/[[...slug]].tsx/events/:slug— src/pages/events/[slug].tsx/leaderboard/:id— src/pages/leaderboard/[id].tsx/auctions/:slug?— src/pages/auctions/[[...slug]].tsx/tools/:slug— src/pages/tools/[slug].tsxP2 — 索引 / 信息流页面流量大但每条路由的 meta 基本是静态的重点确认 title / description / canonical 已显式设置而非继承默认值/、/home、/models、/images、/videos、/posts、/articles、/bounties、/collections、/comics、/comics/browse、/challenges、/challenges/winners、/events、/tools、/builds以及/search/models|images|articles|bounties|collections|comics|tools|users对应 src/pages/index.tsx、src/pages/models/index.tsx、src/pages/search/models.tsx 等。P3 — 营销 / 常青 / 法律页面应在.com上完整收录、可受益于更丰富 meta/schema 的静态或近静态页面/content/:slug*TOS/Privacy 等 catch-allsrc/pages/content/[[...slug]].tsx、/pricing、/safety、/newsroom、/support、/creator-program、/changelog、/product/vault、/product/link、/product/odor、/shop、/gift-cards、/buzz/marketplace。P4 — Sitemaps站点地图必须与每页的deIndex决策一致——向 Google 提交一个返回noindex的 URL 是矛盾信号/sitemap-models.xml— src/pages/sitemap-models.xml/index.tsx/sitemap-articles.xml— src/pages/sitemap-articles.xml/index.tsx/sitemap-tools.xml— src/pages/sitemap-tools.xml/index.tsx决策项是否补 posts、images、bounties、collections、comics、users、events、challenges 的 sitemap。应 de-index 的路由sanity-check 分组抽查这些页面不需要 SEO 打磨但必须稳定输出noindex以免污染 SERP。按组抽查组内全部渲染 noindex 即勾选编辑 / 创建 / 向导类articles/[id]/edit、articles/create、models/[id]/edit、models/[id]/wizard、models/[id]/model-versions/…、models/create、models/train、posts/[postId]/edit、posts/create、bounties/[id]/edit、bounties/create、bounties/[id]/entries/create、bounties/[id]/entries/[entryId]/edit、comics/create、comics/project/[id]/*、train、training/[workflowId]、generate账户 / 账单类user/account、user/notifications、user/membership、user/buzz-dashboard、user/downloads、user/transactions、user/vault、user/referrals、user/earn-potential、user/pool-estimate、user/stripe-connect/onboard认证 / 领取 / 重定向类login、login/token、verify-email、redirect、region-blocked、preview-restricted、redeem-code、claim/buzz/[id]、claim/cosmetic/[id]、intent/avatar、intent/post、discord/link-role、studio/confirm、subscribe/[plan]、purchase/buzz支付类payment/*、tipalti/setup收藏辅助类collections/[collectionId]/join、collections/[collectionId]/review、collections/youtube/auth游戏 / 一次性页面games/chopped、games/knights-of-new-order、dev/onboarding、data-graph-v2、images/iterate版主 / 内部moderator/*、research/*、testing/*。六、已落地案例Articles 详情页的修复文档中唯一已完成并登记的修复是/articles/:id/:slug?2026-04-24其实现可作为其他 P0 页面的改造范本。核心代码位于 src/pages/articles/[id]/[[...slug]].tsx 第 383–402 行Meta经由Gated的metaprop 注入Gated contentNsfwLevel{article.nsfwLevel} bypassRating{isOwner} suppressAds{!article.publishedAt} meta{{ title: ${article.title} | Civitai, description: truncate(articleBodyText, { length: 150 }), images: article?.coverImage, ogEndpoint: /api/og?typearticleid${article.id}, canonical: getArticleUrl({ id: article.id, title: article.title }), alternate: /articles/${article.id}, schema: articleSchema, breadcrumb: buildBreadcrumbSchema(env.NEXT_PUBLIC_BASE_URL ?? , [...]), ogType: article as const, deIndex: !article?.publishedAt || article?.availability Availability.Unsearchable, }} 对照审计清单逐项核验✅Meta在门控之外由Gated组合保证Gated内部先渲染Meta {...finalMeta} /再渲染门控分支见 src/components/Gated/Gated.tsx 第 223–249 行✅og:image使用/api/og?typearticleid…图片兜底由Meta的getIsSafeBrowsingLevel过滤✅deIndex覆盖未发布 /Unsearchable/green 域名 !hasSafeBrowsingLevel(article.nsfwLevel)三种来源其中后一种由文档记载的修复加入与Gated的shouldDefaultDeIndex形成双保险⚠️ 残留风险description是truncate(removeTags(article.content), 150)——若 NSFW 文章漏入可索引集合可能向 SERP 泄漏露骨文本。绿域deIndex守卫在实践上缓解了该风险但若未来决定索引.red仍需处理。七、未决问题Open Questions文档明确列出的四个待决策项任何后续改动都应显式回答.red是否应被索引当前canIndex在.red上仅因 Host 匹配即为真。索引 NSFW URL 本身合法成熟内容搜索存在需求但牵涉广告网络、安全搜索合规与外链画像。应显式决策而不是让它成为canIndex Host 匹配的副作用。canonical 格式一致性。Articles 以/articles/:id/:slug为 canonical、/articles/:id为 alternate。其他实体类型应遵循同一约定否则需文档化说明分歧。/api/og的韧性。OG 端点是所有分享链接的主要社交图来源需确认它对 NSFW-但-模糊预览场景始终渲染 SFW 卡且在实体缺失时优雅降级返回可展示内容而非 500。Sitemap 覆盖率。sitemap 是否遵循与页面相同的 green/NSFW de-index 规则sitemap 中出现返回noindex的 URL 对 Google 是矛盾信号。八、工具链用爬虫视角验证每一条规则文档给出三层验证手段配合上文源码即可形成「代码 → 线上行为」的闭环Google Search ConsoleGSC作为「已收录 vs 已提交」数量与 coverage errors 的真相来源任何代码侧发现都应配一次 GSC 查询确认真实影响。逐页验证对线上站点执行curl -A Googlebot url这是最快看到爬虫实际收到的内容meta 标签与正文的方式——尤其是验证正文跳转卡片与 meta 描述之间的不匹配是否已被noindex消除。渲染路径差异dev-server 渲染足够检查 meta 标签但不足以验证完整 SSR 输出当服务端渲染路径如canIndex的 Host 判定、Gated的门控状态机成为关键时应使用生产构建pnpm run buildpnpm run start验证。小结从审计文档到可执行规则把整份文档压缩成三条可迁移的工程规则门控与 meta 分离Meta永远渲染在可见性门控之外保证爬虫能读到结构化元数据门控负责正文呈现Meta负责索引声明二者通过deIndex协作而非互相遮蔽。评级感知的 noindex 合成noindex 由「页面显式deIndex」或「全局!canIndex」或「对话框打开状态」任一触发NSFW 内容在绿域上必须落入其中一条让.red的 URL 赢得 canonical 之争。sitemap 与页面决策对齐任何被 noindex 的 URL 都不该出现在 sitemap 中任何 sitemap 中的 URL 都必须可被爬虫无矛盾地收录。对同类型「多域名 内容分级」的站点docs/seo-audit.md与其对应源码Meta、Gated、_app.tsx、useDomainColor构成了一套可直接照抄的审计模板与实现范式。【免费下载链接】civitaiA repository of models, textual inversions, and more项目地址: https://gitcode.com/GitHub_Trending/ci/civitai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考