Hugo + Stack主题:打造极简技术博客的配置与美化指南
2026/9/17 14:59:16 网站建设 项目流程

我想做极简技术博客的时候,第一反应就是 Hugo 配上 Stack 主题。Hugo 是 Go 写的静态站点生成器,本地预览、打包都很快;Stack 主题则很克制,没有花哨的动画,也没有硬塞一堆前端框架,打开页面就是一屏一屏干净的文字。如果你也想搭一个自己的技术博客,或者已经在用 Stack 但觉得默认效果不够有辨识度,这篇内容你可以直接照着操作。下面我会把 3 个必改配置和 5 个高级美化技巧拆开讲,每一步都带实际文件和代码。另外,如果你的 Hugo 项目现在还放在机械硬盘或者移动硬盘上,我也会在部署和备份部分专门聊到这个,因为硬盘速度对本地预览的影响,真比你想象中大。

1. 为什么是 Hugo 和 Stack 主题

1.1 Stack 主题到底解决了什么问题

技术博客的核心需求其实很朴素:能写 Markdown、能分类标签、能搜索、能归档、打开速度快。很多博客系统不是做不到,而是把简单的事情做复杂了。 WordPress 也能搭技术博客,但你可能要先处理插件兼容、缓存插件、安全更新、数据库备份一堆事情。Hexo 和 VuePress 也很火,但 Node 生态的构建链路相对重,依赖一多,升级一次可能就要折腾半天。Hugo 不需要数据库,不需要运行时,写完 Markdown 后跑一条命令,就直接输出整个静态网站。

Stack 主题能在国内技术圈流行起来,靠的不是功能堆叠,反而是“不做多余的事”。它的首页是卡片式文章列表,侧边栏放头像、简介、搜索、分类、标签。文章页有目录、阅读时间、上一篇下一篇,这些技术博客的刚需功能都有,但页面没有多余的弹窗、返利插件、访问计数器之类的东西。对读者来说,打开页面就是内容本身;对作者来说,维护成本低到可以忽略。

另外一个容易被忽略的点是移动端体验。Stack 的排版在手机上不需要放大缩小,字号和行距都调得比较舒服。这也是我坚持用它做技术博客的原因:很多读者第一次访问你的文章可能是在通勤路上,如果移动端一塌糊涂,内容再硬也留不住人。

1.2 动手前的环境准备

开始之前,你需要先确认电脑上有 Git 和 Hugo。Hugo 建议装 extended 版本,因为 Stack 主题的样式用到了 SCSS,普通版在构建时会因为缺少相关能力报错。

hugo version git --version

如果没有安装,去 Hugo 官方 GitHub Releases 页面下载对应系统的预编译包即可。安装完以后,打开命令行建站:

hugo new site blog cd blog git init git submodule add https://github.com/CaiJimmy/hugo-theme-stack.git themes/stack

这里使用 git submodule 而不是直接下载 zip,是方便后续跟进主题更新。如果以后 Stack 主题发布了新版本,你只需要在项目目录里执行git submodule update --remote就能更新主题,不用手动覆盖文件。

拿到主题后,先把主题自带的示例站点配置复制到项目根目录:

cp -r themes/stack/exampleSite/* .

这一步很关键。Stack 主题不是只靠一个config.toml就能跑的,它把配置拆分到了config/_default/目录下的多个文件里。直接复制 exampleSite,能让你少踩很多配置缺失的坑。之后运行:

hugo server -D

浏览器打开http://localhost:1313,如果能看到一个带侧边栏的示例博客,说明环境已经通了。

2. 3个必改配置:从默认模板改成自己的博客

复制完 exampleSite 之后,你看到的仍然是演示内容。接下来要做的 3 个改动,是让这个站点真正变成“你的博客”的必经步骤。

2.1 必改配置一:站点核心参数

打开config/_default/config.toml,最重要的几个字段如下:

baseURL = "https://yourname.example.com" languageCode = "zh-cn" title = "我的技术博客" theme = "stack" paginate = 10 enableEmoji = true hasCJKLanguage = true

baseURL一定要填你最终部署的完整域名。如果留空或者填成http://localhost:1313/,后续生成的 sitemap、canonical、Open Graph 标签都会是错的,搜索引擎收录时会出现一堆本地地址。

hasCJKLanguage对中文博客非常重要。Hugo 在计算摘要和阅读时间时,对中英文的统计方式不同。开了这个参数之后,中文文章的自动摘要和阅读时间会更接近真实体验。

paginate = 10是首页每页显示的文章数量。如果你想走极简风,10 篇比较合适;如果你的文章普遍很长,也可以改成 5 或 6。

搜一下某一篇文章标题需要单独设,实际上 Hugo 的搜索是 JavaScript 在前端做的。Stack 主题用的是 index.json 索引,你只需要在侧边栏配置里加上搜索组件就行。

2.2 必改配置二:菜单和导航

默认的菜单还是示例站点的,需要改成你自己的导航。在config/_default/menus.toml里,配置大致是这样的:

[[main]] name = "首页" url = "/" weight = 1 [[main]] name = "归档" url = "/archives/" weight = 2 [[main]] name = "标签" url = "/tags/" weight = 3 [[main]] name = "关于" url = "/about/" weight = 4

这里的weight决定菜单顺序,数字越小越靠前。注意 URL 要和你的 content 目录结构对应。比如你想要“关于”页面,就得先在 content 下新建:

hugo new about/index.md

Stack 主题的文章和普通页面是分开处理的。普通页面默认不会出现在文章流里,而是可以作为独立页面存在。写完/about/的内容后,导航里再有对应菜单项,页面就能访问到了。

我踩过一个坑:当时只改了菜单,没有新建about页面,结果点“关于”直接 404。后来改成先建页面、再改菜单,顺序对了就不会有问题。

2.3 必改配置三:文章模板和摘要策略

Hugo 新建每篇文章时,会根据archetypes/default.md生成 front matter。你可以把这个模板改成最适合自己习惯的样子:

--- title: "{{ replace .Name "-" " " | title }}" description: "" date: {{ .Date }} draft: true tags: [] categories: [] featuredImage: "" featuredImagePreview: "" ---

featuredImage是文章详情页的封面图,featuredImagePreview是列表卡片上用的缩略图。如果只填一个,Stack 可能会用同一个图补齐另一个位置。图片路径建议放到static/images/下,然后写/images/xxx.jpg

摘要这块,新手很容易忽略。Stack 在列表页展示文章摘要时,有几种优先级:如果在 front matter 里写了description,就用它;如果没写,Hugo 会从正文里自动截取。自动截取的长度由全局配置summaryLength控制,默认大概是 70 个词。中文场景下,70 个词的自动截断结果常常会切在奇怪的位置。

我的建议是每篇文章都手动写description。一来能精确控制列表页的展示效果,二来对 SEO 也更友好。如果你有很多旧文章不想回头补,直接在config.toml里调大summaryLength也能缓解,但不推荐依赖这个方式。

3. 5个高级美化技巧:把 Stack 调成自己喜欢的样子

完成了必改配置之后,你的博客已经可以正常用了。但默认的 Stack 主题长什么样,你大概也猜得到:白色背景、黑色文字、蓝色链接。想让博客有自己的识别度,可以从下面 5 个方向入手。

3.1 技巧一:自定义头像、简介和社交链接

Stack 的侧边栏是整站辨识度最高的地方。默认情况下,侧边栏会读取主题示例里的人物信息。要改成你自己的信息,打开config/_default/params.toml找到 sidebar 相关配置。

不同版本的 Stack 主题字段名会有一点点差异,但大方向一致。常见的配置内容类似下面这样:

[sidebar] name = "你的名字" bio = "写代码,也写字" avatar = "/images/avatar.png"

如果字段名对不上,不要硬记,直接打开themes/stack/exampleSite/config/_default/params.toml对照示例。Stack 的文档并不是特别丰富,但 exampleSite 本身就是最好的配置说明。

头像图建议用 200x200 左右的正方形图片,压缩成 WebP 或者压缩过的 PNG。不要直接放一张几 MB 的原图,因为侧边栏在每一个页面都会加载,图片越小整站越快。社交链接一般放在简介下面,比如 GitHub、RSS、Email 这些。RSS 这个一定要留,技术博客的老读者很依赖它。

3.2 技巧二:深色模式和主题色

Stack 默认带了深色模式切换按钮,不需要你自己写一套 JS。但如果你觉得切换后的默认配色不够有质感,可以通过自定义 CSS 覆盖。

Stack 支持在项目根目录创建assets/css/custom.css,这个文件会被主题自动合并。你不需要修改主题源码,就能覆盖大部分样式。举个例子,我想让链接色从默认的蓝改成更沉稳的靛蓝色:

:root { --stack-color-link: #2563eb; } [data-theme="dark"] { --stack-color-link: #60a5fa; }

这里用到了 CSS 变量。Stack 主题的很多颜色都是变量控制的,你只要在浏览器的开发者工具里选中正文区域,就能看到当前生效的颜色变量名。改的时候注意不要一上来就加!important,优先修改变量,这样主题升级时不容易冲突。

如果你只是想给卡片加点圆角和阴影,也可以直接在 custom.css 里写:

.article-card { border-radius: 12px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); }

极简不等于没有质感,适当的圆角和阴影能让页面显得更精致。但别陷入过度设计。我见过不少博客,最后视觉上很花哨,字体一大堆,颜色也五花八门,反而不如默认清爽。

3.3 技巧三:用 Shortcode 自制提示框

写技术文章经常要表达“注意”“警告”“推荐”这类信息。如果每次都用引用块,时间久了视觉上会很单调。Hugo 的 Shortcode 机制允许你自定义内容组件,Stack 本身已经支持了一些,但你也可以自己加。

layouts/shortcodes/notice.html里创建一个提示框模板:

<div class="notice {{ .Get "type" }}"> <div class="notice-title">{{ .Get "title" }}</div> <div class="notice-body">{{ .Inner | markdownify }}</div> </div>

然后在assets/css/custom.css里加一点样式:

.notice { border-left: 4px solid var(--stack-color-link); background: rgba(0, 0, 0, 0.03); padding: 12px 16px; margin: 20px 0; border-radius: 4px; } .notice-title { font-weight: 700; margin-bottom: 6px; }

写文章的时候这样用:

{{< notice type="warning" title="注意" >}} 这里的内容会显示在提示框里。 {{< /notice >}}

这种方法的好处是,提示框的样式和内容分离。如果你以后想换风格,只改一处 CSS 就能全局生效。

3.4 技巧四:定制文章元信息、标签样式和阅读进度条

Stack 默认会在文章头部显示日期、阅读时间、作者这些信息。这些东西本身够用,但如果你希望它更符合个人习惯,可以修改文章卡片对应的 partial 文件。Stack 的文章 header 相关模板在themes/stack/layouts/partials/article/components/下,你可以把想改的文件复制到项目的layouts/对应目录里覆盖,而不是直接改主题目录。

标签样式也是很容易出效果的地方。默认标签就是一个普通链接,你可以把它改成胶囊样式:

.tags a { border: 1px solid var(--stack-color-link); border-radius: 999px; padding: 2px 10px; margin-right: 6px; font-size: 0.85rem; }

这会让文章底部的标签区域看起来更整洁,也不会显得花哨。

阅读进度条是 Stack 默认没有的东西。如果你实在想要,可以在layouts/partials/reading-progress.html里写一小段脚本,然后在baseof.html的底部引入。但我要提醒一句:改baseof.html意味着主题升级时需要手动合并。我的做法是只在 baseof 里保留一行 include,其他代码全部抽到独立 partial 文件里,这样升级冲突的概率会低很多。

实际上,Stack 默认已经在文章页显示了阅读时间。我用了阅读进度条一段时间后,还是觉得默认的“预计阅读 X 分钟”更省心。博客到底要不要加这个,取决于你自己。

3.5 技巧五:SEO、Open Graph 和分享图

美化不只停留在页面视觉,搜索引擎和社交平台上的展示效果,也属于博客形象的一部分。Hugo 自带 Open Graph 模板,但你需要把baseURL配好。否则对方在微信、Twitter 里分享你的链接时,抓取到的地址都是错的。

如果想给整站设定一个默认分享图,把一张 1200x630 左右的图片放到static/images/og-default.png,然后在config/_default/params.toml里指定:

images = ["/images/og-default.png"]

单篇文章可以用 front matter 里的featuredImageimages来覆盖默认分享图。分享图不要用太小的图,社交平台会对小图进行模糊放大,效果很差。建议用文字加上简单底色的风格,这样在聊天窗口里一眼就能看出是哪篇文章。

另外,建议在每篇文章的 front matter 里写description。这个描述不仅会在列表页显示,也会被搜索引擎用来做搜索摘要。没有摘要的文章,在搜索结果里可能就是一段断句混乱的正文截取,点击率会明显受影响。

4. 从硬盘到线上:构建、部署与备份

配置和美化都做完之后,接下来就是把博客真正发布到线上。这个环节看着简单,但如果你没有处理好本地目录和部署流程,后面维护会很难受。

4.1 本地预览和构建

日常写作时,我会用:

hugo server -D

-D是让草稿文章也出现在本地预览里。写完后,正式构建时建议加--gc--minify

hugo --gc --minify

--gc会清理构建缓存里的无用文件,--minify会把 HTML、CSS、JS 压缩。构建完成后,public/目录就是整站静态文件。你可以扔给任何静态托管服务,不需要服务器执行代码。

如果你在本地想验证生产环境效果,不要直接双击public/index.html。正确做法是起一个静态服务器:

python3 -m http.server 8080 -d public

然后访问http://localhost:8080。直接用file://协议打开时,很多静态站点的路径和资源加载会出问题,但那不是你的博客有问题,而是本地协议限制。

关于硬盘这块,我想多说一句。Hugo 的构建速度虽然快,但在机械硬盘或者移动硬盘上跑,文件监听和资源写入都会明显变慢。我第一次把项目放在移动硬盘上写博客时,hugo server每次保存文件后的热更新都要好几秒,后来把项目移到 SSD 上,基本是保存完立即刷新。所以建议:项目源码放在 SSD 上开发,移动硬盘用来做冷备,而不是直接当开发目录。

4.2 部署到托管平台

Hugo 的部署方式非常多。最简单省心的是用 Git 托管平台自带的静态站点能力,或者用支持 Hugo 构建的 Pages 服务。我用下来最舒服的方式是 GitHub Actions 自动构建。只要往主分支 push,就会自动构建并发布。

一个能用的 GitHub Actions 配置大概是这样的:

name: deploy on: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: recursive - uses: peaceiris/actions-hugo@v3 with: hugo-version: "0.138.0" extended: true - run: hugo --minify - uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./public

这里最容易漏掉的是with: submodules: recursive。如果你用 git submodule 添加主题,没有这一项,GitHub Actions 拉代码时不会拉主题,构建必然失败。

部署完之后,一定要去检查https://你的域名/sitemap.xml是否正常,然后去 Google Search Console 或 Bing Webmaster 提交站点。Hugo 会自动生成 sitemap,但搜索引擎不会主动知道你建了博客,需要你手动提交。

4.3 硬盘上的 Hugo 站点备份

很多技术博主只备份public目录,这是错误的。public是从源码生成的产物,丢了可以从源码重新构建。真正不能丢的是你的源码源文件、图片资源、config/_default/配置文件、主题版本信息。

我的备份习惯是:整个项目目录同步到移动硬盘,同时推送到私有 Git 仓库。Git 仓库只需要包含以下内容:

  • content/文章源代码
  • assets/自定义样式和布局
  • static/图片和其他静态资源
  • config/配置目录
  • .gitmodules主题子模块信息
  • go.modgo.sum如果有模块依赖

themes/stack因为是 git submodule,不需要单独备份,但.gitmodules文件必须保留。没有这个文件,换一台电脑后你很难知道自己用的是哪个版本的主题。

如果你把整个项目放在机械硬盘上做备份,建议压缩成 tar 或 zip,不要只靠散文件。因为机械硬盘长期通电后坏道风险会增加,压缩成一个归档文件至少能减少碎片化存储带来的问题。

5. 常见问题与排查技巧实录

这个部分是我实际使用 Hugo + Stack 过程中踩过的坑,整理成速查表,方便你遇到问题时直接对照。

现象常见原因解决办法
页面样式全部丢失baseURL配错或者没有拷贝 exampleSite 的配置目录检查config/_default是否存在,确认baseURL是完整域名
首页文章列表不显示params.toml里的mainSections和你的 content 目录不一致mainSections改成实际存放文章的 section,比如["posts"]["blog"]
搜索功能没结果本地预览时页面协议限制,或者没有生成 index.json部署线上再测;本地可以用静态服务器访问而不是file://
本地刷新很慢项目在机械硬盘或者移动硬盘上,文件监听跟不上把项目移到 SSD,或使用hugo server --renderToMemory

5.1 页面样式全丢

如果你本地打开页面发现完全没样式,第一步检查浏览器开发者工具里的网络请求,看看 CSS 文件返回的是 404 还是正常。如果是 404,多半是配置目录不完整。Stack 主题的主题样式位于themes/stack/assets/css/,但真正启用它,需要 config 里正确指定theme = "stack",并且确保assets目录下的自定义文件没有语法错误。

5.2 文章列表不显示

Stack 默认的mainSections["posts"]。也就是说,它只会在content/posts/目录下找文章。如果你习惯把内容放在content/blog/,但mainSections没改,首页就会是空的。修改方式是在params.toml里加上:

mainSections = ["blog"]

注意,这个字段是数组结构,不要写成mainSections = "blog"。多个目录也可以,比如["posts", "notes"]

5.3 标签和分类页打不开

Stack 的分类、标签页依赖 taxonomy 特性。如果你的 config 里没有正确配置相关内容,标签页会 404。检查config.toml里有没有:

[taxonomies] tag = "tags" category = "categories"

如果没有,Hugo 就不知道tagscategories是什么,自然无法生成对应页面。这个字段一般 exampleSite 里已经带上了,如果你是自己从空项目开始搭的,很容易漏。

5.4 主题升级后自定义样式丢失

很多人喜欢直接改themes/stack底下的文件。这样做不是不行,但每次git submodule update --remote更新主题时,你的修改会被覆盖。正确做法是把要覆盖的模板复制到项目根目录的layouts/下,让项目的layouts优先级高于主题的layouts。这样升级主题时,项目级文件不会被覆盖。

我在升级 Stack 主题时遇到过一个问题:主题改了某个 CSS 类名,我之前写在 custom.css 里的选择器失效了。排查方式很简单,打开线上页面查看具体元素的 class,再和 custom.css 里的选择器对比。如果发现失效,更新选择器就好。

最后再说一个我自己的习惯。每次写完文章,我不会直接 push,而是先跑一遍hugo --gc --minify,再本地起一个静态服务器,把新文章点开看一眼:封面图有没有显示、代码高亮是否正常、标签链接能不能点、分享出去之后标题和摘要对不对。确认没问题再推远端。这个顺序帮我省掉了非常多线上问题。

博客不是越复杂越好。Hugo 加 Stack 这套组合,最核心的价值就是把维护成本压到最低,让你把时间留给写作本身。至于那些美化技巧,选你自己真正喜欢的,够用就好。如果你按照上面这些步骤走完,接下来要做的,就是安安心心写第一篇正式文章了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询