前言#
搭建一个个人博客,我选择了以下技术栈:
| 组件 | 选型 | 作用 |
|---|---|---|
| 静态生成器 | Hugo | 将 Markdown 转为静态网页 |
| 代码托管 | GitHub | 存储博客源码和内容 |
| 部署平台 | Cloudflare Pages | 自动构建并部署到全球 CDN |
| 内容管理 | Decap CMS | 提供可视化的文章编辑界面 |
这套方案的优势:完全免费、全球加速、自动部署、支持可视化编辑。
一、安装 Hugo#
macOS#
brew install hugoWindows#
winget install Hugo.Hugo.Extended验证安装#
hugo version
# hugo v0.164.0+extended ...建议安装 extended 版本,支持 SCSS 编译。
二、初始化 Hugo 项目#
创建站点#
hugo new site my-blog
cd my-blog安装主题#
这里以 hugo-book 主题为例,使用 git submodule 方式安装:
git init
git submodule add https://github.com/alex-shpak/hugo-book themes/hugo-book基础配置#
编辑 hugo.toml:
baseURL = "https://your-domain.com/"
locale = "zh-cn"
defaultContentLanguage = "zh"
theme = "hugo-book"
paginate = 10
[params]
BookTheme = "auto" # 自动切换明暗主题
BookToC = true # 显示目录
BookSection = "posts" # 文章所在 section
BookSearch = true # 启用搜索
BookDateFormat = "Jan 2, 2006"
[markup]
[markup.highlight]
codeFences = true
style = "dracula" # 代码高亮主题
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true # 允许 HTML
[menu]
[[menu.after]]
identifier = "posts"
name = "文章"
url = "/posts/"
weight = 20创建第一篇文章#
hugo new content posts/hello-world.md编辑生成的文件:
---
title: "你好世界"
date: 2026-01-01T10:00:00+08:00
draft: false
tags: ["介绍"]
categories: ["通用"]
summary: "我的第一篇博客文章"
---
## 欢迎来到我的博客
这是我的第一篇博客文章!本地预览#
hugo server -D
# 访问 http://localhost:1313三、项目目录结构#
搭建完成后,项目结构如下:
my-blog/
├── archetypes/ # 文章模板
│ └── default.md
├── assets/ # 需要处理的静态资源(SCSS、JS)
├── content/ # 内容文件
│ ├── posts/ # 文章
│ │ └── hello-world.md
│ └── menu/ # 菜单配置
├── data/ # 数据文件
├── i18n/ # 国际化翻译
├── layouts/ # 自定义布局模板
├── resources/ # Hugo 生成的资源缓存
├── static/ # 静态文件(图片、CSS 等)
├── themes/ # 主题目录
│ └── hugo-book/ # hugo-book 主题
├── hugo.toml # 主配置文件
└── public/ # 生成的静态站点(不提交到 Git)四、推送到 GitHub#
创建 GitHub 仓库#
- 登录 GitHub,创建新仓库
- 仓库名建议使用
username.github.io(自动获得 GitHub Pages 域名,但我们会用 Cloudflare)
初始化并推送#
# 初始化 Git(如果还没做)
git init
# 创建 .gitignore
cat > .gitignore << 'EOF'
public/
resources/_gen/
.DS_Store
.env
node_modules/
EOF
# 提交
git add .
git commit -m "init: Hugo blog with hugo-book theme"
# 关联远程仓库并推送
git remote add origin https://github.com/your-username/my-blog.git
git branch -M main
git push -u origin main五、配置 Cloudflare Pages#
5.1 登录 Cloudflare#
- 访问 dash.cloudflare.com
- 注册或登录账号
5.2 创建 Pages 项目#
- 左侧菜单选择 Workers & Pages
- 点击 Create → Pages → Connect to Git
- 授权 GitHub 并选择你的博客仓库
- 配置构建设置:
| 设置项 | 值 |
|---|---|
| Production branch | main |
| Framework preset | Hugo |
| Build command | hugo |
| Build output directory | public |
- 添加环境变量:
| 变量名 | 值 |
|---|---|
HUGO_VERSION |
0.164.0(与本地版本一致) |
- 点击 Save and Deploy
5.3 自定义域名(可选)#
- 在 Pages 项目中点击 Custom domains
- 输入你的域名(如
blog.example.com) - 按提示添加 CNAME DNS 记录:
blog.example.com → your-project.pages.dev - 等待 SSL 证书自动签发(通常几分钟)
5.4 自动部署#
配置完成后,每次推送到 main 分支,Cloudflare Pages 会自动:
- 拉取最新代码
- 执行
hugo构建 - 部署到全球 CDN
六、配置 Decap CMS(可视化编辑器)#
Decap CMS(原 Netlify CMS)提供了一个网页端的文章编辑界面,让你不用接触代码就能写文章。
6.1 添加 CMS 文件#
创建 static/admin/index.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="noindex" />
<title>内容管理</title>
</head>
<body>
<script src="https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js"></script>
</body>
</html>创建 static/admin/config.yml:
backend:
name: github
repo: your-username/my-blog # 你的 GitHub 仓库
branch: main
base_url: https://your-worker.workers.dev # OAuth Worker 地址
app_id: your_github_app_id # GitHub OAuth App ID
locale: zh_Hans
media_folder: "static/images"
public_folder: "/images"
collections:
- name: "posts"
label: "文章"
folder: "content/posts"
create: true
slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
path: "{{slug}}/index"
fields:
- { label: "标题", name: "title", widget: "string" }
- { label: "发布日期", name: "date", widget: "datetime" }
- { label: "草稿", name: "draft", widget: "boolean", default: false }
- { label: "标签", name: "tags", widget: "list", allow_add: true }
- { label: "分类", name: "categories", widget: "list", allow_add: true }
- { label: "摘要", name: "summary", widget: "text", required: false }
- { label: "正文", name: "body", widget: "markdown" }6.2 创建 GitHub OAuth App#
- 访问 GitHub Developer Settings
- 点击 New OAuth App
- 填写信息:
| 设置项 | 值 |
|---|---|
| Application name | Blog CMS |
| Homepage URL | https://your-domain.com |
| Authorization callback URL | https://your-worker.workers.dev/callback |
- 记录 Client ID
- 生成 Client Secret 并记录
6.3 部署 OAuth Worker#
使用 Cloudflare Worker 来处理 OAuth 认证流程。
安装 Wrangler CLI:
npm install -g wrangler创建 Worker 项目:
mkdir cloudflare-worker && cd cloudflare-worker创建 wrangler.toml:
name = "blog-oauth"
main = "src/index.js"
compatibility_date = "2024-01-01"创建 src/index.js(OAuth 处理逻辑):
const ALLOWED_USERS = ["your-github-username"];
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (request.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders() });
}
switch (url.pathname) {
case "/auth":
return handleAuth(url, env);
case "/callback":
return handleCallback(url, env);
default:
return new Response("Not Found", { status: 404 });
}
},
};
function handleAuth(url, env) {
const clientId = env.GITHUB_CLIENT_ID;
const redirectUri = `${url.origin}/callback`;
const githubAuthUrl = new URL("https://github.com/login/oauth/authorize");
githubAuthUrl.searchParams.set("client_id", clientId);
githubAuthUrl.searchParams.set("redirect_uri", redirectUri);
githubAuthUrl.searchParams.set("scope", "repo,user");
githubAuthUrl.searchParams.set("state", crypto.randomUUID());
return Response.redirect(githubAuthUrl.toString(), 302);
}
async function handleCallback(url, env) {
const code = url.searchParams.get("code");
if (!code) {
return new Response("Missing code", { status: 400 });
}
try {
// 用 code 换取 access token
const tokenRes = await fetch(
"https://github.com/login/oauth/access_token",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({
client_id: env.GITHUB_CLIENT_ID,
client_secret: env.GITHUB_CLIENT_SECRET,
code,
}),
}
);
const tokenData = await tokenRes.json();
if (tokenData.error) {
return new Response(`Error: ${tokenData.error_description}`, {
status: 400,
});
}
// 验证用户身份
const userRes = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${tokenData.access_token}`,
Accept: "application/vnd.github.v3+json",
},
});
const userData = await userRes.json();
if (!ALLOWED_USERS.includes(userData.login)) {
return new Response("Access Denied", { status: 403 });
}
// 返回成功页面,传递 token 给 CMS
return new Response(
generateSuccessHtml(tokenData.access_token),
{
headers: { "Content-Type": "text/html;charset=UTF-8", ...corsHeaders() },
}
);
} catch (error) {
return new Response(`Error: ${error.message}`, { status: 500 });
}
}
function generateSuccessHtml(token) {
return `<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>授权成功</title></head>
<body>
<p>授权成功,窗口将自动关闭...</p>
<script>
(function() {
var token = "${token}";
function receiveMessage(e) {
var msg = "authorization:github:success:" + JSON.stringify({
token: token, provider: "github"
});
window.opener.postMessage(msg, e.origin);
}
window.addEventListener("message", receiveMessage, false);
if (window.opener) {
window.opener.postMessage("authorizing:github", "*");
}
setTimeout(function() { window.close(); }, 3000);
})();
</script>
</body>
</html>`;
}
function corsHeaders() {
return {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
};
}设置环境变量并部署:
# 登录 Cloudflare
wrangler login
# 设置 GitHub OAuth 密钥
wrangler secret put GITHUB_CLIENT_ID
# 输入你的 Client ID
wrangler secret put GITHUB_CLIENT_SECRET
# 输入你的 Client Secret
# 部署
wrangler deploy部署成功后会得到一个 Worker 地址,如 https://blog-oauth.your-subdomain.workers.dev。
6.4 使用 CMS#
访问 https://your-domain.com/admin/ 即可打开 CMS 界面:
- 点击 Login with GitHub
- 授权后进入管理界面
- 可以可视化地创建、编辑、删除文章
- 编辑完成后点击 Publish,会自动提交到 GitHub 并触发部署
七、常用工作流程#
写文章(本地)#
# 创建新文章
hugo new content posts/my-new-post.md
# 本地预览
hugo server -D
# 编辑文章内容...
# 确认无误后提交
git add .
git commit -m "post: add my new post"
git push
# Cloudflare Pages 自动部署写文章(CMS)#
- 访问
/admin/ - 点击 New 文章
- 填写标题、标签、正文
- 点击 Publish
- 自动提交到 GitHub 并部署
八、总结#
通过 Hugo + GitHub + Cloudflare Pages 的组合,我们搭建了一个:
- ✅ 完全免费的博客系统
- ✅ 全球 CDN 加速,访问速度快
- ✅ 自动部署,推送即发布
- ✅ 可视化编辑,降低写作门槛
- ✅ Markdown 写作,内容可迁移
- ✅ 版本控制,所有内容有迹可循
整套系统搭建完成后,你只需要专注于写作本身,技术细节交给自动化流程处理。