
一直想搭个自己的博客,记录一些技术思考和随笔杂记。要求很简单:
- 📝 写 Markdown 就行,别折腾
- 🆓 全程免费,不花一分钱
- 🚦 推送代码后自动部署
- 🌙 支持暗黑模式、代码高亮、目录
- 🏷️ 支持标签、分类、RSS
最终选了 Hugo + PaperMod + Cloudflare Pages + GitHub Actions 这套方案。
整个过程从安装到上线大约 2 小时(主要是踩坑),下面是完整记录。
技术选型#
对比了几个主流方案:
| 框架 | 构建速度 | 部署难度 | 主题生态 | 推荐度 |
|---|
| Hugo | ⚡ 极快(Go 二进制) | 简单 | 丰富(300+) | ⭐⭐⭐⭐⭐ |
| Astro | 快 | 简单 | 增长中 | ⭐⭐⭐⭐ |
| Hexo | 中(Node.js) | 简单 | 丰富 | ⭐⭐⭐⭐ |
| Jekyll | 慢(Ruby) | 简单(GitHub Pages 原生) | 丰富 | ⭐⭐⭐ |
| Zola | 快(Rust) | 简单 | 少 | ⭐⭐⭐ |
最终选 Hugo:单二进制零依赖,构建秒级完成,PaperMod 主题开箱即用,支持暗黑模式、TOC、代码高亮、RSS 等所有需求。
整体架构#
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
| ┌─────────────────────────────────────────────────────────┐
│ 你的本地电脑 │
│ │
│ 写 Markdown 文章 → hugo new content/posts/xxx/index.md │
│ ↓ │
│ hugo server -D 本地预览 │
│ ↓ │
│ git add . && git commit && git push │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ GitHub 仓库 │
│ │
│ main 分支 push 触发 GitHub Actions │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ GitHub Actions CI │
│ │
│ 1. checkout 代码(含 submodule) │
│ 2. 安装 Hugo extended │
│ 3. hugo --minify 构建静态资源 │
│ 4. 部署到 Cloudflare Pages │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Cloudflare Pages │
│ │
│ 全球 CDN 加速,免费 SSL,自动分发 │
│ 访问地址:https://xiaohuang-blog.pages.dev │
└─────────────────────────────────────────────────────────┘
|
全程自动化,你只需要 写文章 + push。
项目结构#
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
| my-blog/
├── .github/
│ └── workflows/
│ └── deploy.yml # ⭐ GitHub Actions CI/CD 配置
├── archetypes/
│ └── default.md # 文章模板(新建文章自动套用)
├── assets/ # 自定义 CSS/SCSS
├── content/ # 📝 博客文章内容
│ └── posts/
│ ├── hello-world/
│ │ └── index.md # 文章用 Bundle 方式管理
│ └── blog-setup-guide/
│ ├── index.md # 文章本体
│ └── images/ # 文章配图(和文章同目录)
├── data/ # 数据文件(导航、友链等)
├── layouts/ # 模板覆盖(可选)
├── static/ # 全站静态资源
│ ├── images/ # 全站共用图片
│ └── favicon.ico # 网站图标
├── themes/
│ └── PaperMod/ # ⭐ 主题(git submodule)
├── .gitignore
├── .gitmodules # 子模块配置
├── hugo.toml # ⭐ Hugo 主配置文件
└── README.md
|
详细步骤#
1. 安装 Hugo#
1
2
3
4
5
6
| # macOS
brew install hugo
# 验证(需要 extended 版支持 SCSS)
hugo version
# 输出:hugo v0.166.0+extended ...
|
2. 初始化项目#
1
2
3
4
5
6
| # 创建站点
hugo new site my-blog && cd my-blog
git init -b main
# 添加 PaperMod 主题
git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
|
3. 配置 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
| baseURL = 'https://xiaohuang-blog.pages.dev'
languageCode = 'zh-CN'
title = '小黄的博客'
theme = 'PaperMod'
paginate = 10
enableRobotsTXT = true
[params]
author = '小黄'
description = '记录一些自己的思考,随笔杂记'
defaultTheme = 'auto' # auto 跟随系统 / dark / light
ShowReadingTime = true # 显示阅读时间
ShowShareButtons = true # 显示分享按钮
ShowPostNavLinks = true # 上一篇/下一篇
ShowBreadCrumbs = true # 面包屑导航
ShowCodeCopyButtons = true # 代码复制按钮
ShowToc = true # 显示目录 TOC
TocOpen = true # 默认展开目录
# 首页 Profile 模式
[params.profileMode]
enabled = true
title = '小黄的博客'
subtitle = '记录一些自己的思考,随笔杂记'
[[params.profileMode.buttons]]
name = '📝 文章'
url = '/posts'
[[params.profileMode.buttons]]
name = '🏷️ 标签'
url = '/tags'
# 社交链接
[[params.socialIcons]]
name = 'github'
url = 'https://github.com/your-username'
[[params.socialIcons]]
name = 'rss'
url = '/index.xml'
# 导航菜单
[menu]
[[menu.main]]
identifier = 'home'
name = '🏠 首页'
url = '/'
weight = 10
[[menu.main]]
identifier = 'posts'
name = '📝 文章'
url = '/posts'
weight = 20
[[menu.main]]
identifier = 'categories'
name = '📂 分类'
url = '/categories'
weight = 30
[[menu.main]]
identifier = 'tags'
name = '🏷️ 标签'
url = '/tags'
weight = 40
# 分类法
[taxonomies]
category = 'categories'
tag = 'tags'
# 代码高亮(Chroma)
[markup.highlight]
codeFences = true
guessSyntax = true
lineNos = true # 显示行号
noClasses = false # 使用 Chroma CSS(推荐)
style = 'monokai' # 代码主题
tabWidth = 4
# 输出格式(RSS)
[outputs]
home = ['HTML', 'RSS', 'JSON']
|
4. 文章模板#
archetypes/default.md:
1
2
3
4
5
6
7
8
9
10
| ---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
draft: true # true=草稿,发布时改 false
toc: true # 显示目录
TocOpen: true # 默认展开目录
description: '' # 文章摘要(首页列表 + SEO)
tags: [] # 标签
categories: [] # 分类
---
|
5. GitHub Actions 配置#
.github/workflows/deploy.yml:
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
| name: Build & Deploy to Cloudflare Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
deployments: write
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.166.0'
extended: true
- name: Build
run: hugo --minify
- name: Deploy to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ secrets.CLOUDFLARE_PROJECT_NAME }}
directory: ./public
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
branch: main
|
6. Cloudflare 配置#
- 登录 Cloudflare Dashboard
- Workers & Pages → Create application → Pages → Create using direct upload
- 项目名:
xiaohuang-blog - 创建 API Token:My Profile → API Tokens → Create Custom Token
- 权限:Account → Cloudflare Pages → Edit
- 获取 Account ID(右侧栏显示)
7. GitHub Secrets 配置#
GitHub 仓库 → Settings → Secrets and variables → Actions:
| Name | Value |
|---|
CLOUDFLARE_API_TOKEN | Cloudflare API Token |
CLOUDFLARE_ACCOUNT_ID | Cloudflare Account ID |
CLOUDFLARE_PROJECT_NAME | xiaohuang-blog |
踩坑记录#
坑 1:子模块缺失 .gitmodules#
现象:Actions 报错 No url found for submodule path 'themes/PaperMod'
原因:用 git clone 而不是 git submodule add 拉取主题,缺少 .gitmodules 文件
解决:创建 .gitmodules:
1
2
3
| [submodule "themes/PaperMod"]
path = themes/PaperMod
url = https://github.com/adityatelange/hugo-PaperMod.git
|
坑 2:Wrangler 默认部署到 Workers#
现象:部署后域名是 .workers.dev 而不是 .pages.dev
原因:Wrangler v4+ 默认把 Pages 部署到 Workers 平台
解决:通过 API 直接创建传统 Pages 项目:
1
2
3
| curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/pages/projects" \
-H "Authorization: Bearer $TOKEN" \
-d '{"name":"xiaohuang-blog","production_branch":"main"}'
|
坑 3:API Token 权限不足#
现象:Authentication error (401)
原因:Cloudflare 没有"Edit Cloudflare Pages"模板,自定义 Token 权限配置不对
解决:创建自定义 Token,权限必须包含 Account → Cloudflare Pages → Edit
坑 4:OAuth Token 无法创建 API Token#
现象:Unauthorized to access requested resource
原因:Wrangler 的 OAuth Token 权限有限,不能通过 API 创建新 Token
解决:只能在 Dashboard 手动创建 API Token
常见问题#
图片怎么放?#
Bundle 方式(推荐):图片和文章放同一目录
1
2
3
4
| content/posts/my-post/
├── index.md
├── cover.jpg ← 封面图
└── screenshot.png ← 文中插图
|
文章中引用:
1
2
3
4
5
6
7
| ---
cover:
image: cover.jpg
alt: '封面描述'
---

|
全局方式:放 static/images/,引用 /images/photo.jpg
视频怎么放?#
1
2
3
4
5
6
7
8
9
10
| <!-- HTML5 原生播放器 -->
<video controls width="100%" poster="cover.jpg">
<source src="/videos/demo.mp4" type="video/mp4">
您的浏览器不支持视频标签。
</video>
<!-- 第三方嵌入(推荐) -->
<iframe src="//player.bilibili.com/player.html?bvid=BVxxxxxx"
width="100%" height="480" frameborder="0" allowfullscreen>
</iframe>
|
新建文章后本地预览#
1
2
| hugo server -D # -D 包含草稿文章
# 浏览器打开 http://localhost:1313
|
发布文章#
把 Front Matter 中 draft: true 改为 draft: false,然后 push 即可。
日常使用手册#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 1. 新建文章
hugo new content/posts/文章标题/index.md
# 2. 编辑内容(把 draft 改为 false)
vim content/posts/文章标题/index.md
# 3. 本地预览
hugo server -D
# 4. 提交推送(自动触发构建 + 部署)
git add .
git commit -m "post: 文章标题"
git push
# 等 1-2 分钟,访问 https://xiaohuang-blog.pages.dev 查看效果
|
| 项目 | 方案 |
|---|
| 静态生成 | Hugo (Go) |
| 主题 | PaperMod |
| 代码托管 | GitHub |
| CI/CD | GitHub Actions |
| 部署 | Cloudflare Pages |
| 费用 | 0 元 |
| 构建时间 | ~100ms |
| 部署时间 | ~30s |
| 功能 | 暗黑模式、代码高亮、TOC、标签、分类、RSS |
整套方案零成本、自动化、维护低。你只需要专注于写 Markdown 文章,剩下的全部自动化 ✨