SCHEMA

schema 的职责不是描述视觉,而是描述页面的事实结构

John Ousterhout 的做法是让每层只承担单一职责。这个 schema 就只负责内容形状、section 顺序和链接关系,不负责皮肤和实现细节。

ANATOMY

一个完整页面的三段式骨架

document object、thin route、host rewrite 现在分别承担三段职责。

DOCUMENT
export const myPage = siteDocumentSchema.parse({
  slug: 'my-page',
  path: '/my-page',
  title: 'My Page',
  description: 'Structured content with a switchable skin.',
  privacy: 'private',
  defaultTheme: 'noir',
  themeOptions: ['noir', 'paper', 'frame'],
  hero: {
    eyebrow: 'PRIVATE ROUTE',
    title: 'Title',
    subtitle: 'Role / Signal / Positioning',
    body: 'Keep copy here, not in the renderer.',
    tags: ['Schema First', 'Theme Switchable'],
    actions: [{ label: 'Open Styles', href: '/styles' }],
    stats: [{ label: 'Themes', value: '3' }]
  },
  sections: [],
  footer: { note: 'schema + theme + renderer', links: [] }
});
ROUTE
export default async function Page({
  searchParams,
}: {
  searchParams?: Promise<Record<string, string | string[] | undefined>>;
}) {
  const params = (await Promise.resolve(searchParams)) ?? {};
  const theme = Array.isArray(params.theme) ? params.theme[0] : params.theme;

  return <SiteRenderer document={myPage} themeId={theme} />;
}
HOST
export function middleware(request: NextRequest) {
  const host = request.headers.get('host') ?? '';

  if (host.includes('styles.zondev.top')) {
    return rewrite('/styles' + request.nextUrl.pathname);
  }
}
SECTION KINDS

当前支持的 section kinds

这套 catalog 现在已经覆盖 intro / hiring / docs / proof / CTA 几类常见页面。以后先问能否复用这些 kind,再决定是否扩新的。

NARRATIVE

用于长段叙事、方法说明、定位解释。

paragraphs
aside?
LIVE PREVIEW
narrative preview
kind: narrative
NARRATIVE

Narrative section

当你需要用完整句子说清楚思路时。

这类 section 适合表达判断、方法和上下文,而不是离散卡片。

如果只是几个要点,就不要硬塞 narrative,用 cards 或 metrics 会更清楚。

METRICS

用于并排呈现几个强信号或关键数字。

items[]
LIVE PREVIEW
metrics preview
kind: metrics
METRICS

Metrics section

Routes
Thin
Themes
3
Renderer
1
Reuse
High
CARDS

用于 feature、proof、problem-decision-impact 这类离散内容。

columns
cards[]
LIVE PREVIEW
cards preview
kind: cards
CARDS

Cards section

Problem

手工堆页面

页面一多就会越来越散。

Decision

统一 schema

先稳定结构和边界。

Impact

复用更便宜

以后更多时间花在内容,不花在重复排版。

TIMELINE

用于经历、版本演进、迭代过程。

entries[]
LIVE PREVIEW
timeline preview
kind: timeline
TIMELINE

Timeline section

v0
Single page

Manual

先做出一个可用版本。

  • 验证方向
  • 暴露维护问题
v1
System page

Structured

把页面升级成 schema + theme + renderer。

  • 开始有复用
  • 开始有 docs
STEPS

用于 playbook、操作流程、生产顺序。

steps[]
LIVE PREVIEW
steps preview
kind: steps
STEPS

Steps section

STEP 01

Write data

先写 document 和 section 顺序。

STEP 02

Pick theme

再决定皮肤,不复制 route。

STEP 03

Render

最后才让 route 负责装配。

QUOTE

用于原则、结论、判断标准。

quote
attribution?
note?
LIVE PREVIEW
quote preview
kind: quote
QUOTE

Quote section

先让内容可迁移,再让视觉可升级。

Site System v1
LINKS

用于联系方式、入口页、下一步动作。

links[]
note?
LIVE PREVIEW
links preview
kind: links
COMPARISON

用于 before/after、旧方案/新方案、A/B 对照。

columns
rows[]
LIVE PREVIEW
comparison preview
kind: comparison
COMPARISON

Comparison section

Topic
Single page
Site system
Copy placement

散在 route 和 JSX 里。

集中在 data object 里。

Theme switch

靠复制页面切明暗。

靠 theme token 切明暗。

FAQ

用于 docs 常见问题、招聘方疑问、使用说明。

items[]
LIVE PREVIEW
faq preview
kind: faq
FAQ

FAQ section

什么时候该扩 section kind?OPEN

当结构真的不同,而不是 copy 变化时。

什么时候只要换 data?OPEN

当页面骨架不变,只是内容、顺序或链接变化时。

SPOTLIGHT

用于 CTA、结论强化、章节转场。

body
actions[]
metrics[]
LIVE PREVIEW
spotlight preview
kind: spotlight
SPOTLIGHT

Spotlight section

既能承接正文,也能承接动作。

这个 kind 是为了避免每次需要大号强调区时都新写一套特别版式。

Reuse
High
RULE

只有结构变化,才值得新增 kind

如果只是内容不同、主题不同、顺序不同,那都应该继续落回 data 或 theme。 新增 kind 的门槛要高,否则 schema 很快会退化成“页面版本列表”。