跳转到主要内容

首页与落地页

用一份本地 YAML 组合首页:Hero、卡片、能力面板、时间线、定价、案例、下载。任意页面也能用同一套分区做成落地页。

首页不是模板,是一份数据:data/home/<语言>.yaml 里的 sections 列表决定页面从上到下有哪些分区,每个分区的内容在同一份文件里按名字取。普通页面加 layout: landing 也能用同一套分区。

分区全部在服务端渲染。价格、star 数、截图、头像、下载状态都必须在 Hugo 启动前就存在于仓库中,没有分区会在浏览器里取数据。

从 Docsy 的 blocks/* 首页迁移过来的站点要重写首页:主题没有 blocks/coverblocks/sectionblocks/feature 这些 shortcode,保留它们会让构建报 template for shortcode "blocks/cover" not found。两条出路是本页讲的 data/home/<语言>.yaml,或者给一个普通页面加 layout: landing

首页的数据来源

首页的内容文件只留标题与描述:

content/_index.zh.md
---
title: OINK
description: 本地优先、仅依赖 Hugo 的技术文档主题
---

分区数据按语言分文件:

首页数据

  • data/
    • home/
      • en.yaml英文站首页
      • zh.yaml中文站首页

查找顺序是 data/home/<当前语言>.yamldata/home/en.yaml → 单语言站点的 data/home.yaml

文件结构只有两层:一个 sections 列表,加上被列表引用的同名键。

data/home/zh.yaml 的骨架
sections:
  - hero          # 用 hero: 键的数据
  - capabilities
  - type: cards   # 用 cards 分区,但读 release: 键的数据
    key: release
  - cta

hero: { … }
capabilities: { … }
release: { … }
cta: { … }

这是本站首页的写法,完整文件见仓库的 data/home/zh.yaml

最小可用首页

粘贴下面这段,替换文字与链接即可发布。链接写成不带前导斜杠的站内路径,主题会补上当前语言前缀(docs/start//zh/docs/start/)。

data/home/zh.yaml
sections:
  - hero
  - cards
  - cta

hero:
  eyebrow: 本地优先 · 仅依赖 Hugo
  title_lines:
    - words:
        - { text: PGSTY OINK }
  lead: 组件写在 Markdown 里,资源随主题分发,一份内容产出四种输出。
  image:
    light: images/hero-light.webp
    dark: images/hero-dark.webp
    alt: OINK 工程文档插图
  actions:
    - { label: 十分钟上手, url: docs/start/, icon: fa-solid fa-rocket, style: primary }
    - { label: 看组件, url: docs/components/, style: ghost }

cards:
  eyebrow: 能做什么
  title: 工程文档需要的都在里面
  columns: 3
  items:
    - title: Markdown 原生组件
      desc: 提示块、标签页、参数表、文件树都是 Markdown 语法的一部分。
      icon: fa-solid fa-cubes
      url: docs/components/
    - title: 四态输出
      desc: HTML、打印、Markdown、RSS,同一份内容不丢信息。
      icon: fa-solid fa-file-export
      url: docs/customize/agents/
    - title: 本地优先
      desc: 字体、图标、搜索、图表运行时全部随主题分发,不连 CDN。
      icon: fa-solid fa-plug-circle-xmark
      url: docs/about/features/

cta:
  title: 从一个能跑的双语站点开始。
  text: 克隆文档站,删掉不要的,改成自己的。
  label: 开始使用
  url: docs/start/
  style: primary

Hero

Hero 是首屏,唯一一个带大标题与配图的分区。

data/home/zh.yaml
hero:
  eyebrow: OINK 0.4.0 · 本地优先          # 标题上方的小字,带状态点
  title_lines:                            # 逐行控制的大标题
    - words:
        - { text: PGSTY OINK }
  lead: 一句话说清这是什么。                 # 支持行内 Markdown 与 <br>
  note: 无需 Node.js                       # 带图标的补充行
  note_icon: fa-solid fa-circle-check
  title_size: 4.25rem                     # 只接受 rem / em / px
  image:
    light: images/hero-light.webp
    dark: images/hero-dark.webp           # 只给一个时深浅色共用
    alt: 首屏插图
  media:
    ratio: '1fr 240px'                    # 文案与配图的列宽
    max_width: 240px
    hide_below: md                        # sm | md | lg | xl 以下隐藏配图
  actions:
    - { label: 开始使用, url: docs/start/, icon: fa-solid fa-rocket, style: primary }
    - { label: GitHub, url: 'https://github.com/pgsty/oink', external: true, style: ghost }
  detail: { label: 看看它长什么样, url: docs/about/showcase/ }

不写 title_lines 时用 title,两者都没有时用站点标题。配图是 CSS 背景图,alt 有值时容器带 role="img",无值时对辅助技术隐藏。

align: center 是纯文字的居中首屏:文案块加宽居中,标题自动平衡换行,note 挪到按钮下方。它不接受 image,两者同时出现构建失败。

分区注册表

22 种分区,名字用连字符(旧数据里的下划线会被规范化)。除 Hero 之外,每种都共用 eyebrow / title / desc(或 text)三个抬头字段与一个 class

类型 放什么
hero 首屏:大标题、按钮、跟随主题的配图
metrics 数字事实,可选计数动画与来源链接
capabilities 左右交替的能力叙事 + 专用视觉面板
principles 编号的产品原则
cards 通用卡片集合:功能、场景、入口
logo-wall 工具与伙伴,网格或纯 CSS 跑马灯
gallery 截图墙
testimonials 引语与署名
contributors 人、角色、头像与链接
faq 折叠或平铺的问答
markdown 一段自由 Markdown
cta 结尾的行动号召
pricing 价格档位卡片
pricing-compare 档位功能对比矩阵
command-box 一条可复制的命令
steps 有序流程,可带命令
timeline 带日期的里程碑
code-plate 展示面板里的代码
preview 一段 Markdown 源码与它渲染出来的样子并排
case-study 案例:指标 + 引语 + 出处
download 一个或多个 data/download/ 记录
bar-chart 不用图表 JS 的数值对比

写错类型名不会静默消失:构建时给一条 unknown section type 警告并跳过该分区。CI 里加上 --panicOnWarning 即变成构建失败。

常用分区的最小写法

卡片与能力面板是最常用的两种。cardscolumns 控制列数:

data/home/zh.yaml
cards:
  title: 应用场景
  columns: 4
  link_label: 了解详情
  items:
    - title: 书籍出版
      meta: 长篇
      icon: fa-solid fa-book-open
      desc: 编号图表式例、交叉引用、索引与整本打印。
      url: docs/write/book/

capabilities 是一屏一条能力,右边配一块结构化的视觉面板,visual.type 只能是 shellcomponentscodeimagecard 五种之一:

data/home/zh.yaml
capabilities:
  eyebrow: 价值主张
  title: 工程文档所需的能力,开箱即用
  items:
    - ref: 01 / 工程文档
      title: 为工程师与文档站设计
      url: docs/start/
      motto: 从第一次构建到长期维护都没有额外阻力
      bullets:
        - '开箱即用的[部署上线](docs/admin/deploy/)体验'
        - '自带[全文检索](docs/customize/search/)与[多语言](docs/customize/i18n/)'
      value: 内容团队把时间用在文档上,而不是重复搭站点。
      visual:
        type: code
        title: build.sh
        lines:
          - { class: c, prefix: '# ', text: 一条命令,一份确定性输出 }
          - { class: p, prefix: '$ ', text: hugo --gc --minify }
          - { class: ok, prefix: '✓ ', text: public/ 可以部署 }
另外十种场景分区的最小 YAML

这些片段摘自主题仓库的可执行回归夹具 tests/site/data/landing/demo/en.yaml,字段名可照抄。

metrics:
  title: 事实
  animate: true
  items:
    - { value: 2189, compact: true, label: Stars, source: { label: 本地 CI 数据, url: 'https://example.org/' } }
    - { value: 32, suffix: '+', label: 语言 }

command-box:
  title: 安装
  code: hugo mod get github.com/pgsty/oink
  lang: bash
  note: 复制按钮由按需加载的 Landing 运行时提供。

steps:
  title: 三步上线
  items:
    - { title: 克隆, desc: 复制文档站仓库。 }
    - { title: 配置, desc: 改三处配置。, cmd: { code: hugo server } }
    - { title: 发布, desc: 推上 GitHub Pages。 }

timeline:
  title: 项目历程
  items:
    - { date: '2024', title: 原型, desc: 第一批数据驱动分区。 }
    - { date: '2026', title: 场景组件, desc: Landing 成为可复用外壳。 }

code-plate:
  title: 页面配置
  aria_label: 示例配置
  lang: yaml
  code: |
    layout: landing
    landing: pricing

preview:
  title: 所写即所得
  file: guide.md            # 源码面板抬头里的文件名,默认 page.md
  source: |                 # 右侧用站点自己的渲染钩子渲染这段 Markdown
    > [!TIP] 只用 Markdown
    > 提示块、步骤、标签页,都是普通语法。

    1. 写 Markdown
    2. 运行 `hugo`
    {.steps}

case-study:
  title: 迁移结果
  stats:
    - { value: 12, label: 可复用分区 }
    - { value: 0, label: 远程请求 }
  quote: “一份 YAML 取代了一个定制页面模板。”
  source: 站点维护者

pricing:
  title: 价格
  tiers:
    - name: 社区版
      price: 免费
      period: 永久
      desc: 完整开源能力。
      features: [全部组件, 社区支持]
      cta: { label: 下载, url: docs/start/ }
    - name: 专业版
      featured: true
      price: ¥24K
      period: /年
      features: [优先响应, 发布包]
      cta: { label: 联系我们, url: 'mailto:[email protected]' }

pricing-compare:
  title: 档位对比
  tiers: [社区版, 专业版]
  groups:
    - name: 支持
      rows:
        - { name: 优先响应, cells: [N, Y] }
        - { name: 年费, price_row: true, cells: [免费, ¥24K] }

download:
  title: 下载
  keys: [prd5]

bar-chart:
  title: 构建耗时
  unit: 
  items:
    - { label: 首次构建, value: 12.3, group: cold }
    - { label: 热缓存, value: 1.6, group: warm, note: 同一台机器上的重复构建。 }

download 分区消费的就是发布与下载页里那份 data/download/<key>.yaml,不引入第二套版本模型。

任意页面做落地页

普通内容页加两行 front matter 即成为落地页:全宽画布,保留顶栏、命令面板与页脚,去掉侧栏与目录。

content/pricing.zh.md
---
title: 价格
layout: landing
landing: pricing
---

数据放在与首页平行的目录下,同样按语言分文件:

落地页数据

  • data/
    • landing/
      • pricing/
        • en.yaml
        • zh.yaml

非首页落地页按这个顺序查找数据,找不到则构建失败,不会渲染空页面:

  1. 页面 front matter 里的 sections
  2. data/landing/<key>/<精确语言>.yaml
  3. 单文件 data/landing/<key>.yaml 里的精确语言条目;
  4. 英文或无语言后缀的记录。

数据量小时可以写在 front matter 里,但 landing:sections: 互斥

content/pricing.zh.md
---
title: 价格
layout: landing
sections:
  - type: hero
    data:
      title: 只用 Hugo 发布产品页面
      actions:
        - { label: 阅读文档, url: docs/, style: primary }
  - type: download
    data: { title: 下载, keys: [prd5] }
  - cta
---

分区条目写法

sections 的每一项可以是一个类型名字符串,也可以是一个 Map:

作用
type 分区类型;省略时用 key 当类型
key 从哪个键取数据,默认与 type 同名;同一种分区用两次时用它区分
data 内联数据,不再到顶层查找键
id 分区的锚点 ID,默认由 key / type 生成
enabled: false 停用这个分区,保留数据
partial 换成站点自己的 partial。属于本地模板约定,不是可移植的 Landing 数据

多语言与本地事实

叙事文字优先分语言文件(zh.yaml / en.yaml)。共享的事实记录也可以在字段级回退:<字段>_<精确语言><字段>_<主语言><字段>,语言标签里的 - 规范化成 _。中文站解析 title_zh_cntitle_zhtitle。不接受 camelCase 后缀。

分区里的显示文字是站点数据,不是主题的 i18n 字符串。只有跑马灯暂停、定价状态这类主题自带控件用翻译键。多语言站点的整体配置见多语言

落地页外壳上的几个可选事实也是本地的,写在 hugo.yml 里,运行时不会去取它们:

hugo.yml
params:
  offline_search: true
  ui:
    landing_search: true          # 布尔;只有站点开了 offline_search 才显示命令面板
    github_stars: 2189            # 已提交的数字,不请求 GitHub API
    alt_site: { label: English site, url: 'https://example.com/' }

页脚不属于首页数据:它读 data/footer/<语言>.yaml(单语言站点用 data/footer.yaml),本站两种语言各一份。data/home/<语言>.yaml 里残留的 footer 键会让构建失败并提示新位置。写法见导航与菜单

输出形态

输出 呈现
HTML 完整的静态分区内容,再按需加载 landing.js 做渐显、计数、复制与主题图片切换
打印 内容保留,跑马灯之类的动态面变成静态网格,控件移除
Markdown 标题、正文、列表、表格与代码,不带组件 class
RSS 不输出 Landing 分区

禁用 JavaScript 后服务端文档仍然完整。跑马灯的副本轨道不进无障碍树,暂停用的是不依赖 JavaScript 的复选框;读者开启减少动态效果偏好时,移动与渐显关闭。

验证

  1. 构建零告警:hugo --printPathWarnings --panicOnWarning。类型写错、数据键不存在、landingsections 同时出现都在这一步暴露。
  2. 打开首页与落地页,逐个分区对照数据文件,每种语言各看一遍。
  3. 禁用 JavaScript 后刷新:内容仍在,只是没有动效。
  4. 深浅色各看一遍,确认 image.light / image.dark 都给对。
  5. 部署到子路径时,确认站内链接与图片都带上了前缀。