Hugo 的 Stack 主题功能丰富,但官方 Demo 采用了目录式配置(config/_default/ 下拆分 6 个 TOML 文件),对新手来说拼凑出完整配置并不容易。本文记录了从近乎空白的 hugo.toml 出发,一步步配置出完整 Stack 博客的过程,目标是让读者照做即可获得同样的效果。
最终效果:左侧边栏显示头像和社交链接图标,顶部菜单包含主页/关于/归档/搜索/链接五个入口,首页右侧有搜索/归档/分类/标签云小部件,文章页支持数学公式渲染和自动目录。
1. 安装 Hugo 和 Stack 主题
之前的文章里讲过了,大概就是:
1
2
3
4
| hugo new site myBlog
cd myBlog
git init
git submodule add https://github.com/CaiJimmy/hugo-theme-stack themes/hugo-theme-stack
|
添加 .gitignore:
1
2
3
| public/
resources/
.hugo_build.lock
|
在 hugo.toml 中声明主题:
1
| theme = "hugo-theme-stack"
|
2. 理解 Stack 的菜单机制
这是配置中最容易踩坑的地方:Stack 的左侧菜单项不是在 hugo.toml 中定义的,而是通过各内容页面的 front matter menu.main 字段声明的。
也就是说,你需要在 content/ 下创建对应的页面文件,每个页面的 front matter 中指定菜单名称、权重和图标,Hugo 会自动收集这些信息生成菜单。
3. hugo.toml 完整配置
以下是完整的 hugo.toml,每一段都有注释说明作用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
| baseURL = "https://example.org/"
languageCode = "zh-cn"
title = "你的博客标题"
theme = "hugo-theme-stack"
defaultContentLanguage = "zh"
hasCJKLanguage = true
# 分页:每页显示文章数
[pagination]
pagerSize = 5
# 文章 URL 格式
[permalinks]
post = "/p/:slug/"
page = "/:slug/"
# 中文语言配置
[languages.zh]
languageName = "简体中文"
title = "你的博客标题"
weight = 1
[languages.zh.params.sidebar]
subtitle = "你的副标题"
# Markdown 渲染配置
[markup]
[markup.goldmark]
[markup.goldmark.extensions]
# 数学公式 passthrough:让 $$...$$ 和 \(...\) 原样传递给前端渲染
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
block = [["\\[", "\\]"], ["$$", "$$"]]
inline = [["\\(", "\\)"]]
# 允许原始 HTML(部分 shortcode 需要)
[markup.goldmark.renderer]
unsafe = true
# 文章目录:从 h2 到 h4,有序列表
[markup.tableOfContents]
endLevel = 4
ordered = true
startLevel = 2
# 代码高亮
[markup.highlight]
noClasses = false
codeFences = true
guessSyntax = true
lineNos = true
lineNumbersInTable = true
tabWidth = 4
# 主题参数
[params]
mainSections = ["post"] # 首页展示的文章分类
rssFullContent = true
favicon = "img/avatar.png" # 站点图标,路径相对于 assets/
[params.footer]
since = 2026 # 建站年份
# 侧边栏:头像、副标题、emoji
[params.sidebar]
emoji = "✏️" # 头像下方显示的 emoji ,可置空。有谁知道这玩意到底有什么用?
subtitle = "你的副标题"
avatar = "img/avatar.png" # 头像,路径相对于 assets/
# 文章许可协议
[params.article]
[params.article.license]
enabled = true
default = "Licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)"
# 小部件:首页和文章页分别显示什么
[params.widgets]
homepage = [
{ type = "search" },
{ type = "archives", params = { limit = 5 } },
{ type = "categories", params = { limit = 10 } },
{ type = "tag-cloud", params = { limit = 10 } },
]
page = [{ type = "toc" }] # 文章页显示目录
# 评论(暂不启用)
[params.comments]
enabled = false
# 社交链接图标(显示在侧边栏头像下方)
[[menus.social]]
identifier = "github"
name = "GitHub"
url = "https://github.com/你的用户名"
[menus.social.params]
icon = "brand-github"
# 可继续添加更多社交链接,例如:
# [[menus.social]]
# identifier = "twitter"
# name = "Twitter"
# url = "https://twitter.com/你的用户名"
# [menus.social.params]
# icon = "brand-twitter"
|
关键配置解读
| 配置项 | 作用 | 注意点 |
|---|
params.sidebar.avatar | 侧边栏头像 | 图片放在 assets/img/ 下 |
menus.social | 社交链接图标 | 图标名来自 Tabler Icons,前缀 brand- |
markup.goldmark.extensions.passthrough | 数学公式 | 让 $$...$$ 和 \(...\) 不被 Markdown 引擎转义 |
markup.tableOfContents | 目录范围 | h2 到 h4 是比较合理的层级 |
params.widgets | 首页/文章页小部件 | 首页放搜索/归档/分类/标签云,文章页放 TOC |
4. 创建内容页面
每个页面的 front matter 中 menu.main 定义了它在左侧菜单中的显示。weight 越小越靠前,icon 对应 Tabler Icons 图标名。
本节很长,但好消息是本节也很水。
4.1 首页 — content/_index.md
1
2
3
4
5
6
7
8
| ---
menu:
main:
name: 主页
weight: -100
params:
icon: home
---
|
4.2 关于 — content/page/about/index.md
1
2
3
4
5
6
7
8
9
10
11
12
13
| ---
title: 关于
description: 关于本站及其作者
menu:
main:
weight: -90
params:
icon: user
---
## 关于本站
在这里写你的介绍。
|
4.3 归档 — content/page/archives/index.md
1
2
3
4
5
6
7
8
9
10
| ---
title: 归档
layout: "archives"
slug: "archives"
menu:
main:
weight: -70
params:
icon: archives
---
|
注意 layout: "archives" 是 Stack 主题提供的特殊布局,会自动按时间线展示所有文章。
4.4 搜索 — content/page/search/index.md
1
2
3
4
5
6
7
8
9
10
11
12
13
| ---
title: 搜索
slug: "search"
layout: "search"
outputs:
- html
- json
menu:
main:
weight: -60
params:
icon: search
---
|
outputs: [html, json] 是搜索功能的必要配置,Stack 主题的搜索依赖 JSON 索引。
4.5 链接 — content/page/links/index.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| ---
title: 链接
description: 友情链接
menu:
main:
weight: -50
params:
icon: link
links:
- title: GitHub
description: 全球最大的软件开发平台
website: https://github.com
image: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
comments: false
---
在这里可以添加友情链接。在 front matter 的 `links` 字段中配置即可。
|
links 字段是 Stack 主题的友情链接功能,每项包含 title、description、website、image。
5. 放置头像
将头像图片放到 assets/img/avatar.png,与配置中 params.sidebar.avatar = "img/avatar.png" 对应。
Hugo 会自动从 assets/ 目录查找资源文件,所以配置路径是相对于 assets/ 的。
6. 数学公式渲染
配置分两层:
- hugo.toml 中的 passthrough(已在上面配置):让 Markdown 引擎不处理
$$...$$ 和 \(...\),原样输出到 HTML - 文章 front matter 中启用:每篇需要数学公式的文章,在 front matter 中添加
math: true
示例文章 front matter:
1
2
3
4
5
6
7
8
9
10
| ---
title: "一篇数学文章"
math: true
---
行内公式 $E = mc^2$,块级公式:
$$
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$
|
Stack 主题会在检测到 math: true 时自动加载 KaTeX 渲染引擎。
7. 文章目录
已经在 hugo.toml 中配置了:
markup.tableOfContents:定义 TOC 的标题层级范围(h2-h4)params.widgets.page = [{type = "toc"}]:文章页右侧自动显示 TOC 小部件
无需在文章 front matter 中额外配置,所有文章都会自动显示目录。
8. 菜单图标
左侧菜单图标和社交链接图标使用 Tabler Icons。图标被Stack放在 assets/img/icons/ 目录下,可以直接使用。也可以去Tabler官网下载SVG图标放到自己的图标文件夹里(./assets/icons)使用。
比如说,非常离谱,默认是没有mail图标的,你得自己下一个才方便在主页放一个自己的邮箱按钮。
9. 最终目录结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| myBlog/
├── hugo.toml
├── assets/
│ ├── img/
│ │ └── avatar.png
│ └── icons/
│ └── mail.svg
├── content/
│ ├── _index.md
│ ├── page/
│ │ ├── about/index.md
│ │ ├── archives/index.md
│ │ ├── search/index.md
│ │ └── links/index.md
│ └── post/
│ └── ... (你的文章)
└── themes/
└── hugo-theme-stack/ (git 子模块)
|
10. 预览
打开 http://localhost:1313 即可查看效果。确认无误后,用 hugo 命令生成静态文件到 public/ 目录。