内容站栏目结构:从 50 篇撑到 1000 篇不返工

内容站的分类与 URL 设计指南:栏目 schema、hub 页模板、sitemap 配置,让结构从 50 篇撑到 1000 篇都不用改。

好的栏目结构是隐形的。坏的栏目结构会在第 200 篇时跳出来——一半文章都不知道归在哪。早规划——把分类编码进内容 schema、URL 规则、sitemap——少返工。

问题背景

栏目结构是文章与搜索引擎之间的契约。它告诉 Google “这 30 篇是同一个主题”,告诉读者”你找 X,这里还有 5 篇 X”。2026 年对独立内容站,分类错误是复利最快的规划错误——一改就同时影响 URL、面包屑、sitemap 和内链。

判断标准

  • 预期 18 个月内能写到 200+ 篇。
  • 主题天然能划成 4-8 个明显不同的子方向。
  • 读者会需要浏览或筛选,而不仅仅是搜索。
  • 变现或转化要靠栏目页落地,而不仅是单篇文章。
  • 希望栏目页本身能跑出中等量级关键词排名。

快速结论

用 4-8 个一级栏目(hub)加扁平标签系统,避免子子栏目。栏目当半永久结构维护,标签当弹性维度。

开始前准备

  • 先定 URL 是扁平(/articles/slug/)还是单层嵌套(/hub/slug/)——后续每个决定都受这个影响。
  • 框架支持 collection schema(Astro Content Collections、Next.js MDX + Zod 等)。
  • 手里有 50-100 个候选题目,能做真实归桶练习,不是纸上推演。

实操步骤

  1. 锚定 4-8 个核心名词。 写一句”这个站是干什么的”,挑出 4-8 个核心名词,那些就是 hub。比如 AI 生产力站可能是:ai-applications、ai-tools、indie-dev、prompt-library、troubleshooting。

  2. 每个 hub 压力测试。 列 20-30 个长尾候选题。撑不到 20 个的 hub 太窄——合到别的 hub 或者砍掉。

  3. 分类写进 content schema。 Astro Content Collections(src/content/config.ts)里:

import { defineCollection, z } from 'astro:content';

const HUBS = [
  'ai-applications',
  'ai-tools',
  'indie-dev',
  'prompt-library',
  'troubleshooting',
] as const;

export const collections = {
  articles: defineCollection({
    type: 'content',
    schema: z.object({
      title: z.string().min(8).max(80),
      description: z.string().min(80).max(170),
      urlSlug: z.string().regex(/^[a-z0-9-]+$/),
      category: z.enum(HUBS),                 // 严格属于一个 hub
      subcategory: z.string().optional(),     // 自由格式,可变
      tags: z.array(z.string()).max(8),
      publishedAt: z.date(),
      lang: z.enum(['en', 'zh']),
      translationKey: z.string(),
    }),
  }),
};

z.enum(HUBS) 防漂移——加第 9 个 hub 是显式决定,不是手滑打错字。

  1. URL 规则定下来后写进 astro.config.mjs 推荐扁平 + 语言前缀:
/en/articles/<slug>/            # 文章
/en/category/<hub>/             # 栏目索引
/en/category/<hub>/page/2/      # 分页
/en/tag/<tag>/                  # 标签索引(可 noindex)

Astro 路由:

src/pages/[lang]/articles/[...slug].astro
src/pages/[lang]/category/[hub]/index.astro
src/pages/[lang]/category/[hub]/page/[page].astro
src/pages/[lang]/tag/[tag].astro
  1. 第一天就建每个 hub 的索引页——就算是空的。 hub 模板要有真实内容,不能只是列表。骨架:
---
import { getCollection } from 'astro:content';
const { hub, lang } = Astro.params;
const all = await getCollection('articles',
  (a) => a.data.category === hub && a.data.lang === lang);
const top = all.sort((a, b) => +b.data.publishedAt - +a.data.publishedAt);
---
<h1>{hubTitle(hub, lang)}</h1>
<p>{hubIntro(hub, lang)}</p>           <!-- ~120 字真实介绍 -->
<ul>
  {top.map((a) => (
    <li><a href={`/${lang}/articles/${a.data.urlSlug}/`}>{a.data.title}</a></li>
  ))}
</ul>
<section class="hub-faq">…</section>   <!-- 3-5 条 hub 级 FAQ -->

空 hub 页会被算薄页——一定要有介绍段和 FAQ。

  1. sitemap 给 hub 比文章更高 priority。 hub 0.8,文章 0.6:
<url>
  <loc>https://yourdomain.com/en/category/indie-dev/</loc>
  <priority>0.8</priority>
  <changefreq>weekly</changefreq>
</url>
<url>
  <loc>https://yourdomain.com/en/articles/some-slug/</loc>
  <priority>0.6</priority>
  <changefreq>monthly</changefreq>
</url>
  1. 标签是后加的。 起步最多 8-12 个,每个标签满 8 篇之前都 noindex:
{tagArticleCount < 8 && <meta name="robots" content="noindex,follow" />}
  1. CI 里强制单 hub 归属。 一个简单的 prebuild 检查:
# scripts/check-single-hub.mjs(节选)
for (const article of all) {
  if (!HUBS.includes(article.data.category)) fail(article, 'invalid hub');
  if (Array.isArray(article.data.category)) fail(article, 'multi-hub forbidden');
}
  1. 每 100 篇审一次。 标签少于 5 篇的合并;超过 40 的拆分。审计日期写进 content-ops 日志。

执行检查清单

  • content schema 用 enum 约束允许的 hub——typo 直接挂。
  • 每个 hub 有自己的索引页:介绍 + FAQ + 分页列表。
  • sitemap 给 hub 和文章不同 priority。
  • 标签页满阈值之前保持 noindex,follow
  • prebuild 脚本对非法 hub 分配直接挂构建。

上线后验证

  • Search Console → Performance → Pages:hub URL 应该在 4-8 周内开始累积 hub 级关键词曝光。
  • 用 URL Inspection 抽查 hub URL——确认已收录且渲染出文章列表。
  • sitemap 计数:curl -s https://yourdomain.com/sitemap.xml | grep -c '<loc>' 对得上预期。

容易踩的坑

  • /hub/subhub/subsubhub/slug/ 的多级嵌套,一年内就要重构。检测:任何语言前缀后有 3+ 段路径。
  • 让 hub 野蛮生长,最后变成 15 个 hub 每个只有 5 篇。检测:prebuild 脚本统计每 hub 文章数,低于 12 就告警。
  • 把标签当 hub 用——搜索引擎更看重 hub。
  • hub 中途改名却没做 301,所有积累的权重都丢了。必须改的话,先把 redirect 写进 firebase.jsonvercel.json 再发改名。
  • 允许一篇文章同时属于多个 hub,最后要么 URL 重复要么 canonical 弱。
  • 标签页每个不到 5 篇还放 index——Google 视为薄页。

FAQ

  • 多少个 hub 算多: 独立站第一年超过 8 个 hub 基本都太多,每个 hub 都填不满。
  • hub 页面要不要写内容: 要——大约 120 字介绍、子文章列表、FAQ 都要。空列表页会被算薄页。
  • 标签有 SEO 价值吗: 更多是给读者用,SEO 价值有限。很多站把标签页 noindex,follow 避免薄页问题。SEO 权重靠 hub。
  • 我的方向真的需要子子栏目怎么办: 用扁平 URL,把层级放在面包屑和元数据里,不要写进 URL。
  • subcategory 要进 URL 吗: 不要。subcategory 放 metadata 和面包屑,URL 保持单层。URL 改动最痛,metadata 改动最便宜。

相关阅读

标签: #独立开发 #建站策划 #Pillar / Cluster #SEO #内容运营 #Technical SEO