Github Page + Hexo + Fluid + ChatGPT 部署个人博客
从零搭建一个博客时,最容易混淆的是四件事各自做什么:Hexo 把 Markdown 变成网页,Fluid 决定网页样式,GitHub Pages 托管公开的静态文件,ChatGPT 帮助梳理步骤、写作和检查代码。本站的源文件放在 Yakumo-Sue.github.io,主题以 Git 子模块保存在 themes/fluid。
图 1:源码、构建结果和公开网页的关系。示意图,不是 GitHub 界面截图。
下面先按新手可以复现的顺序走一遍,再给出本站现用的 deploy.yml。文末另有 GitHub 官方推荐的直接部署写法,两种发布方式只能选一种,不能把两份工作流同时启用。
一、准备账号与本地环境
1. 注册并验证 GitHub 账号
- 打开 GitHub 注册页,填写邮箱、密码与用户名,按页面提示完成验证。
- 查收邮件并验证邮箱。未验证邮箱可能无法完成创建仓库等基本操作。
- 登录后建议开启双重验证:头像 → Settings → Password and authentication。用户名会进入博客地址,所以先确定自己想用的名字。
用户主页仓库的名称必须是 你的用户名.github.io。例如用户名为 Yakumo-Sue,仓库就是 Yakumo-Sue.github.io,最终网址为 https://yakumo-sue.github.io/。
2. 安装 Git 与 Node.js
从 Git 官网 安装 Git,从 Node.js 官网 安装 Node.js。本站工作流使用 Node.js 22,Hexo 项目的 package.json 要求 Node.js 20 及以上。安装后重新打开终端,检查:
1 | |
如果命令找不到,先确认安装完成并重开终端,不必先修改博客文件。
二、创建仓库与 Hexo 项目
3. 创建 GitHub Pages 仓库
登录 GitHub,点击右上角 + → New repository,仓库名填写 USERNAME.github.io(把 USERNAME 换成自己的用户名)。个人免费账号可选择 Public。第一次从本地推送时,先不要勾选创建 README、.gitignore 或许可证,避免与本地初始化结果冲突。点击 Create repository。
这里使用“用户主页”仓库。如果使用普通仓库名,例如 my-blog,网址会变成 https://USERNAME.github.io/my-blog/,Hexo 的 url、root 和站内以斜杠开头的图片路径也要跟着调整。
4. 初始化 Hexo
在一个准备存放博客的目录运行:
1 | |
这会产生根目录的 _config.yml、package.json、source/ 和 themes/。本地生成后的 public/ 是成品,不应当作为源码提交到 main。
5. 安装 Fluid,同时保留上游目录结构
Fluid 官方文档对普通新站推荐 npm 安装;本站为了在 themes/fluid 保留主题的 GitHub 文件夹结构,采用 Git 子模块并固定到 v1.9.9:
1 | |
以后在另一台电脑克隆时要带上子模块;工作流的 checkout 也必须写 submodules: recursive。不要直接改子模块内的文件:把本站配置放在根目录 _config.fluid.yml,把自定义 CSS 放在 source/css/,升级主题时才不会混在一起。
在根目录 _config.yml 中确认这些字段(保留文件里的其他设置):
1 | |
再新建 _config.fluid.yml,放入需要覆盖的主题设置。例如:
1 | |
把图片放在 source/img/banner.webp。这里的 _config.fluid.yml 是站点根目录的覆盖配置,themes/fluid/_config.yml 是主题自带默认值。Fluid 的关于页需另建 source/about/index.md,并在 Front Matter 中写 layout: about。
三、用 Markdown 写文章与放图片
文章源码位于 source/_posts/。可以按主题分子目录,例如本站将开篇文章放在 source/_posts/随想/hello-world.md,本文放在 source/_posts/技术手记/。这只是源码组织方式;在 _config.yml 使用 posts/:title/ 时,Hexo 的 :title 会包含相对于 _posts 的子目录。因此,若搬动旧文章但想保持原链接,请在文章头部指定 permalink。
1 | |
普通内容接在第二条分隔线后面。图片存入 source/img/,文章中用绝对路径引用,例如:
1 | |
图 2:Markdown 是源码,public/ 是构建产物。示意图。
在项目根目录先运行:
1 | |
浏览器访问 http://localhost:4000/。本站还提供 npm run build 来生成 public/。每次改完 Markdown 都可以先在本地检查图片、目录与代码块。
四、分清两种 Token:本地推送与自动构建
6. 本地向 GitHub 推送
优先使用 GitHub CLI 的 gh auth login,或 Git Credential Manager 的浏览器授权。若必须使用个人访问令牌(PAT)完成 HTTPS Git 推送,可这样创建:
- GitHub 头像 → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token。
- 填写用途和较短的过期时间;Resource owner 选自己的账号。
- Repository access 选 Only select repositories,只选博客仓库。
- 在仓库权限中给 Contents: Read and write。如果所用令牌还要创建或修改 .github/workflows/,按 GitHub 的权限提示增加 Workflows: Read and write。
- 生成后立即保存在可信的密码管理器中。命令行通过 HTTPS 提示输入密码时,输入 PAT,而不是 GitHub 登录密码。
不要把 PAT 写进 Markdown、工作流、Git 远程 URL、截图或发给 ChatGPT。令牌若泄露,立即在 GitHub 设置中撤销并重新生成。以上 PAT 是本地身份凭据,不是下面工作流的 GITHUB_TOKEN。
图 3:两种令牌所在的位置不同;站点页面不应包含任何真实令牌。
7. GitHub Actions 的 GITHUB_TOKEN
GitHub 会为每次工作流运行自动创建 GITHUB_TOKEN,不需要去 Personal access tokens 页面手工生成,也不需要创建同名仓库 Secret。本站的工作流用 permissions: contents: write 授权它把生成的页面写到同仓库的 gh-pages 分支。权限只给需要写入分支的工作流。
如果将来要访问另一个仓库或第三方服务,才考虑单独的凭据。此时应在仓库 Settings → Secrets and variables → Actions → New repository secret 保存为 Secret,并在工作流使用 secrets.名称;不能把令牌明文提交进 deploy.yml。
五、编写 deploy.yml:本站现用的分支发布方案
在项目根目录创建 .github/workflows/deploy.yml,本站目前使用的完整内容如下:
1 | |
逐项理解它,之后排错才不会只靠复制粘贴:
- on.push.branches 指定推送 main 自动执行;workflow_dispatch 允许在 Actions 页手动运行。
- permissions.contents: write 给本次运行的内建令牌写仓库内容的权限。
- checkout 取回源码与 Fluid 子模块;少了 submodules: recursive,CI 中可能找不到主题。
- setup-node 使用与项目兼容的 Node.js 22,并缓存 npm 下载。
- npm ci 严格按照 package-lock.json 安装;npm run build 执行 Hexo,输出到 public/。
- actions-gh-pages 只把 public/ 的构建结果提交到 gh-pages,不会把 node_modules 或 Markdown 当成网页。
此方案的 Pages 设置:第一次推送后等待 Actions 创建 gh-pages 分支。然后进入仓库 Settings → Pages → Build and deployment,将 Source 选为 Deploy from a branch,分支选 gh-pages、目录选 /(root),点击 Save。
图 4:本站现用方案的设置路径;绘制的界面示意,并非真实账户截屏。
GitHub 文档明确提醒:使用 GITHUB_TOKEN 的工作流向发布分支提交,不会触发后续的 Pages 构建。本站的历史运行中能看到 Build and publish Hexo 与 pages build and deployment 成功,但不能据此保证新仓库也会因该提交自动发布。如果遇到“工作流成功但公开网页未更新”,请使用下一节的官方直接部署方案,并切换 Pages 的 Source。不要同时跑两种 deploy.yml。
六、官方直接部署方案:不使用 gh-pages 分支
对于从零创建、希望避免发布分支触发问题的博客,GitHub 和 Hexo 官方文档采用 upload-pages-artifact + deploy-pages。把 Pages 的 Source 改为 GitHub Actions,并用下面内容替换前一节的 deploy.yml:
1 | |
这里 contents: read 只用来读取源码;pages: write 和 id-token: write 用于直接部署 Pages。upload-pages-artifact 上传构建结果,deploy-pages 发布它;不再使用 peaceiris/actions-gh-pages,也无需写 gh-pages 分支。两套方案的 Pages Source 设置不同,这一点最容易漏掉。
七、提交、查看部署并继续写作
先检查项目的 .gitignore 包含 node_modules/、public/、db.json 和 dist/。本地把源码推送到刚创建的仓库:
1 | |
如果之前已经配置过 origin,使用 git remote -v 检查,不必重复添加。推送后进入仓库 Actions,查看 Build and publish Hexo 或 Deploy Hexo to GitHub Pages 的运行日志;成功后在 Settings → Pages 查看公开地址,再打开博客首页和一篇文章核验链接与图片。部署可能需要几分钟。
之后发布新文章只需编辑 source/_posts/ 下的 Markdown,先本地预览,再提交并推送 main。流水线会重新生成静态页面,无需手工上传 HTML。
ChatGPT 在这条流程中做什么
可以让 ChatGPT 帮你拟标题、整理 Front Matter、审阅 deploy.yml、解释失败日志和绘制示意图。例如:
我使用 Hexo 8、Fluid 主题 Git 子模块、Node.js 22,仓库是 USERNAME.github.io。请检查这份 deploy.yml 是否包含子模块 checkout、npm ci、构建及 GitHub Pages 发布步骤,并指出与 Settings → Pages 选择不一致的地方。
把配置片段和脱敏日志给它即可。令牌、密码和仓库 Secret 的值不要放进提示词。本站的私有预览站与公开的 GitHub Pages 是两个发布目标;GitHub Pages 仍以仓库提交和 Actions 运行结果为准。
八、常见问题按什么顺序查
- 首页 404:确认仓库名是否为 USERNAME.github.io,Pages Source 与当前 deploy.yml 是否配套,Actions 是否成功。
- 首页更新了,文章却 404:检查文章的 permalink、新旧路径,以及生成后 public/posts/ 中是否有对应目录。
- 图片或样式丢失:用户主页仓库通常设置 root: /;项目页面要改站点路径,文章中的 /img/ 绝对路径也要处理。
- CI 报找不到 Fluid:检查 themes/fluid 是否已提交为子模块,.gitmodules 是否存在,checkout 是否启用 submodules: recursive。
- npm ci 失败:本地安装依赖后提交更新过的 package-lock.json,使 package.json 与锁文件一致。
- 推送或发布时报 403:本地确认登录或 PAT 对仓库有写入权限;CI 检查 permissions。不要为了排错公开令牌。
- 构建成功但网页还是旧的:检查 pages build and deployment 是否执行;分支方案可按第六节改用官方直接部署方案。
