用 GitHub + Cloudflare 搭建自己的 Blog 平台
为什么想做这个 Blog
一直想做一个自己的 Blog 平台。
最早的想法很简单:希望有一个属于自己的云端空间,用来学习云端知识,记录学习内容,也方便在不同设备上随时打开、快速查阅和对外展示。
但这个想法之前一直没有真正开始。原因也很现实:自己搭云服务听起来就意味着服务器、运维、域名、部署、安全、备份和持续费用。对个人学习项目来说,如果一开始就要持续付费和长期维护,很容易先被成本劝退。
后来,AI 编程工具逐渐成熟。它把很多原来需要长时间搜索、试错和反复调试的工作,变成了可以快速验证的小步迭代。试错成本明显降低之后,这个 Blog 项目才真正开始推进。
项目起因,是搜索资料时看到别人用 GitHub Pages 搭建个人网站。GitHub Pages 给了一个很好的启发:个人 Blog 不一定要从买服务器开始,也可以先从静态网页开始。于是我先从 GitHub Pages 的思路出发,尝试搭建一个低成本、可维护、可持续迭代的个人 Blog。
随着和 AI 一起不断深入方案,最后发现 GitHub + Cloudflare 更适合这个目标:GitHub 负责代码和版本管理,Cloudflare 负责静态网站托管、域名、CDN、HTTPS,以及后续的边缘函数、数据库和 AI 扩展能力。
所以这篇笔记记录的不是一个“一次性建站教程”,而是一个个人 Blog 从静态网页逐步演进成云端内容平台的过程。
当前成品
当前正式访问地址:
现在它已经不只是一个纯静态 Blog。它包含:
- Markdown 文章发布。
- 首页、文章页、标签、分类、归档。
- 自定义域名和 HTTPS。
- 评论系统。
- 邮箱订阅、退订确认和文章更新通知。
- 友链申请、AI 审核和后台人工管理。
- 管理后台。
- 站内搜索和 AI 问答入口。
- 访问统计、订阅人数、互动数据。
- 社交链接入口。
- Cyber Matrix 矩阵雨背景、头像动画和首页视觉动效。
这也是我对它的新定位:
用低成本云服务,搭一个可持续迭代的个人内容平台。
实际效果截图
下面这些截图来自本地预览环境,用来展示当前 Blog 的公开页面效果。截图只覆盖公开页面和 Admin 登录页,不展示后台数据、Cloudflare 控制台、邮箱、token 或数据库敏感字段。
首页效果

首页主要展示站点名称、标语、矩阵雨背景和右侧信息入口。首页可以更强调氛围感,因为它承担的是第一眼印象。
文章阅读页

文章页更重视阅读体验。背景动效需要降低存在感,避免干扰正文。
友链页面

友链页从静态说明扩展成了可提交、可审核、可自动收录的互动入口。
AI 入口

正常关键词站内搜索

未知关键词站内搜索

正常关键词AI回复

未知关键词AI搜索
AI 入口放在导航栏中,目标是把站内搜索逐步升级为“用问题查文章”的方式。
Admin 后台
下面这些截图来自测试环境后台,只使用示例评论、示例友链、示例订阅和汇总统计,不展示密码、token、邮箱密钥或 Cloudflare 控制台账号信息。

登录页只保留管理员入口,口令在 Cloudflare 环境变量中配置,页面本身不保存明文密码。

概览页把访问分析、待处理事项和热门文章放在一起,方便第一眼确认站点状态。

评论管理按文章归属展示评论、回复、审核状态和删除入口,适合处理垃圾评论和人工回复。

友链管理保留人工审核入口。自动识别失败或需要人工确认的网站,可以在后台补充名称、描述和头像。

订阅页用来查看订阅状态、退订状态和通知失败情况。

通知记录独立成页,便于检查文章更新邮件是否发送成功。

文章数据页展示浏览、点赞、评论和近 7 天趋势,也支持按路径查询单篇文章。

Cloudflare 访问分析主要用于查看近 24 小时或近 7 天请求、访客和带宽变化。
Git Notes 文章管理

项目早期使用 PagesCMS 直接编辑 Blog 仓库文章。随着内容结构稳定,文章已经迁移到独立私有 Notes 仓库,按 Tech、Life、Explore、Collection、Notes 五个目录管理。
每篇 Markdown 同时保存标题、发布时间、永久链接、TDK、标签、内容类型和发布权限。Blog 只读取 visibility: public 的内容,图片也随 Notes 仓库版本化管理。
最终选型
当前 Blog 使用的核心组合是:
- GitHub:分别保存 Blog 源码、Notes 内容和完整版本历史。
- Git Notes 同步:验证公开文章、生成分类与更新时间,并同步到 Blog
test。 - PagesCMS:只管理关于页、友链说明等 Blog 自有页面。
- Hexo:把 Markdown 文章生成静态网页。
- Butterfly:作为 Hexo 主题,提供基础博客布局和阅读体验。
- Cloudflare Pages:托管静态网站并自动部署。
- Cloudflare DNS:管理域名解析和 HTTPS。
- Cloudflare D1:保存评论、友链、订阅、统计等轻量数据。
- Cloudflare Pages Functions:给静态站点增加 API。
- Cloudflare Workers AI / Vectorize:预留和承载 AI 搜索、问答、向量检索能力。
- Resend:发送订阅、退订、评论和文章更新邮件。
- Gemini / Tavily:辅助友链审核与联网搜索证据。
从结果看,这个组合很适合个人站:成本低、部署简单、扩展空间足够,而且每一步都能独立验证。
GitHub 是什么,在这个项目里做什么
GitHub 是代码托管平台。它最重要的能力不是“存代码”这么简单,而是提供版本管理、分支协作、提交记录和远程备份。
在这个 Blog 项目中,GitHub 主要承担这些职责:
- 保存 Blog 源码。
- 保存 Markdown 文章。
- 记录每一次修改历史。
- 使用分支区分测试版本和正式版本。
- 让 Cloudflare Pages 可以从 GitHub 自动拉取代码并构建网站。
当前项目使用两个主要分支:
test:测试分支,用来触发 Cloudflare Pages Preview 部署。main:正式分支,用来触发生产环境部署。
这个流程的好处是:文章、样式、配置和功能改动都先进入测试环境确认,确认没问题后再合并到正式环境。
GitHub Pages 是什么,为什么最后没有只用它
GitHub Pages 是 GitHub 提供的静态网站托管服务。很多个人主页、文档站和简单 Blog 都可以直接放在 GitHub Pages 上。
它的优点是:
- 免费。
- 和 GitHub 仓库天然集成。
- 很适合纯静态页面。
- 上手成本低。
这个项目最初也是受 GitHub Pages 启发。但继续深入后,发现项目需求不只是“把静态页面放出来”。后续还希望有:
- 自定义域名和 HTTPS。
- 更强的 CDN 和缓存能力。
- 评论、订阅、友链、访问统计等轻量动态功能。
- 边缘函数能力。
- 后续 AI 搜索、问答、数据索引等扩展空间。
所以最终选择 GitHub + Cloudflare Pages:GitHub 继续负责源码和分支,Cloudflare 负责部署和云端能力。
Hexo 是什么
Hexo 是一个静态博客生成器。它可以把 Markdown 文件转换成完整的静态网站。
GitHub 地址:
官网:
Hexo 的核心能力包括:
- 使用 Markdown 写文章。
- 自动生成文章页、首页、标签页、分类页和归档页。
- 支持主题系统。
- 支持本地预览。
- 构建后输出纯静态文件,方便部署到任何静态托管平台。
在这个 Blog 中,Hexo 负责把文章生成最终网页。平时只需要写 Markdown,构建时 Hexo 会生成 HTML、CSS、JS、文章列表和搜索索引。
Butterfly 是什么
Butterfly 是 Hexo 生态里一个常用的博客主题。它提供了完整的博客界面和阅读体验。
GitHub 地址:
文档:
Butterfly 主要提供:
- 响应式页面布局。
- 首页、文章页、归档页、分类页、标签页样式。
- 代码块展示。
- 目录导航。
- 文章卡片。
- 搜索入口。
- 页面视觉和交互效果。
在这个 Blog 中,Butterfly 负责基础外观和阅读体验。我们使用它作为主题底座,而不是从零写前端页面。
这样做的好处是:先把精力放在内容、部署和云端能力上,页面基础体验直接站在成熟主题之上。
Cloudflare 是什么,在这个项目里做什么
Cloudflare 是一套云网络和边缘计算平台。它最常见的能力包括:DNS、CDN、HTTPS、网站托管、边缘函数、数据库和安全防护。
在这个 Blog 项目里,Cloudflare 承担这些职责:
- 托管静态网站:Cloudflare Pages。
- 绑定自定义域名:Cloudflare DNS。
- 自动提供 HTTPS 证书。
- 使用 CDN 加速访问。
- 使用 Pages Functions 提供 API。
- 使用 D1 保存轻量数据。
- 使用 Workers AI / Vectorize 支撑 AI 搜索扩展。
- 为后续更多边缘能力留出空间。
Cloudflare 对个人站最友好的地方,是很多能力都有免费额度。对于一个低流量个人 Blog 来说,Pages、Functions、D1、DNS 和 HTTPS 已经可以覆盖大部分需求。
Cloudflare 相关扩展可以单独看这篇:
域名绑定流程
域名绑定的目标是让用户访问自己的域名,而不是默认的 Cloudflare Pages 域名。
当前正式域名是:
1 | blog.fsj.dpdns.org |
大致流程如下:
- 在 Cloudflare 中接入
fsj.dpdns.org这个域名。 - 在 Cloudflare Pages 中打开 Blog 项目。
- 添加自定义域名
blog.fsj.dpdns.org。 - 在 Cloudflare DNS 中添加 CNAME 记录。
- 让
blog.fsj.dpdns.org指向 Cloudflare Pages 默认域名。 - 等待 Cloudflare 完成域名验证和 HTTPS 证书配置。
- 访问
https://blog.fsj.dpdns.org/验证页面是否正常打开。
当前没有强制把裸域名跳转到 Blog。重点只放在:
这种做法更简单,也避免一开始就把根域名用途固定死。以后如果根域名要做导航页、个人主页或其它服务,也可以继续扩展。
从静态 Blog 到可交互平台
最开始的目标只是把文章发布出去。但随着使用深入,静态 Blog 的边界很快出现:读者无法评论,无法订阅更新,友链需要人工改代码,访问统计也没有地方保存。
所以后续在静态站基础上补了几类动态能力。
评论系统
评论系统由前端组件、Pages Functions 和 D1 组成。
基本逻辑是:
- 文章页显示评论区。
- 用户提交评论。
- API 接收并写入 D1。
- AI 审核或后台人工审核。
- 审核通过后在文章页展示。
- 如果开启回复通知,则使用当前浏览器记住的订阅邮箱发送提醒。
这样既保留了静态站部署简单的优点,也让文章具备基础互动能力。
邮箱订阅
订阅功能用于记录读者邮箱,并在文章更新时发送提醒。
当前订阅流程包含:
- 浏览器本地记住订阅状态。
- 已订阅时显示退订、退出和编辑名称入口。
- 重复订阅时识别已有邮箱,并显示欢迎回来。
- 退订需要邮件二次确认。
- 文章更新时可以触发更新通知邮件。
- 订阅人数可以在页面侧边栏展示。
邮件发送由 Resend 负责,发件域名走自己的域名体系。这个部分更详细的记录放在私人 Email 搭建笔记里。
友链系统
友链最初可以手动展示,后来改成自动申请和后台管理。
当前逻辑是:
- 用户提交站点链接和名称。
- 系统先访问链接,访问失败直接返回失败。
- 如果能访问,再进入 AI 审核。
- Tavily 提供联网搜索证据。
- Gemini 或 Cloudflare AI 辅助判断站点是否正常。
- AI 通过则自动收录。
- AI 不确定则进入后台人工审核。
- 管理后台可以手动新增、批准、拒绝或删除友链。
为了避免空头像影响视觉,默认友链头像改成纯色背景和“友”字。没有描述时,默认使用“名称 + blog”的形式。
管理后台
后来单独增加了 Admin 管理界面,用来管理动态数据。
它主要用于:
- 查看统计摘要。
- 管理评论。
- 回复评论。
- 审核友链。
- 人工新增友链。
- 管理订阅用户。
- 查看文章更新通知发送记录。
后台登录做了基础防护:连续错误和滚动错误都会触发锁定,降低暴力尝试风险。登录页也做了独立视觉设计,而不是简单表单。
站内搜索和 AI 问答
站内搜索从传统搜索入口扩展为导航栏里的 AI 入口。
它的目标不是替代文章列表,而是让读者可以用问题的方式查找内容:
- 普通站内搜索:更适合关键词定位。
- Cloudflare AI 搜索:更适合语义查询。
- AI 问答:更适合根据已有文章做总结式回答。
当前这个能力依赖 Cloudflare Workers AI 和 Vectorize。它更像后续知识库能力的起点。
视觉动效
视觉上也做了一些定制:
- 首页标语改为“与 AI 协作,快速验证每一个新想法”。
- 首页和导航区域增加更统一的科技风格。
- 使用 Cyber Matrix 粒子/矩阵雨作为背景。
- 首页可以更明显地展示动效,文章页则降低强度,避免影响阅读。
- 头像从静态图变成带字母切换和光点环绕的动效。
- 订阅、抖音、知乎、B 站等入口统一成一组社交按钮。
- 右侧公告栏改成更像推荐入口的滚动列表。
动效的原则是:首页可以更有氛围,文章页必须让阅读优先。
当前架构图
可以把当前 Blog 理解成四层:
1 | 写作层 |
这套结构的好处是:核心内容仍然是静态生成,稳定、便宜、好缓存;互动能力通过 Cloudflare 的边缘能力补上,不需要自己维护服务器。
本地开发流程
日常写文章时,主要流程是:
- 在 Notes 仓库修改 Markdown 和相关图片。
- 运行内容校验并提交到
notes/test或notes/main。 - Notes push 事件触发 Blog 工作流,生成文章、TDK、分类、更新时间和图片。
notes/test只同步blog/test,部署 Cloudflare Preview。notes/main只同步blog/main,部署 Cloudflare Production。- Blog 框架自身 push 只构建已提交的内容,不重新读取 Notes。
- 如果涉及 API / D1,再补充 Pages 本地或云端验证。
常见命令思路:
1 | npm run serve |
其中 npm run serve 只适合看纯静态页面;如果改了评论、订阅、友链、统计、AI 搜索等功能,就要走 Pages + D1 的本地预览或云端测试。
Git Notes 内容管理

早期内容同时经过 Joplin、PagesCMS 和 Blog 仓库,修改入口过多,容易出现字段不一致和内容被下一次同步覆盖的问题。
现在使用独立私有仓库 feng-shijie/notes 作为文章唯一源头:
- 五个一级目录决定稳定大分类。
- Frontmatter 保存标题、TDK、标签、内容类型和发布权限。
assets/<文章文件名>/保存文章图片。- Git commit 记录修改历史,并提供文章更新时间。
- 仓库校验器阻止无效字段、重复永久链接和缺失图片进入发布流程。
同步流程:
1 | notes/test push -> blog/test -> Cloudflare Preview |
两个分支独立对应,不自动互相合并。Blog 工作流使用只读 Deploy Key 获取事件指定的 Notes commit;同步器只处理 visibility: public,并通过 manifest 限制可覆盖和删除的文件范围。
PagesCMS 的当前职责
PagesCMS 仍可用于轻量编辑,但不再直接修改 Blog 文章。它只管理:
- 关于页。
- 友链说明页。
source/img/uploads/中的 Blog 自有图片。
source/_posts/ 和 source/img/notes/ 是同步生成目录,直接修改会在下一次 Notes 同步时被覆盖。
发布流程
这个 Blog 的发布流程强调“先测试,再正式发布”。
推荐流程:
- 本地完成文章或功能修改。
- 本地构建通过。
- 推送到
test分支。 - 等待 Cloudflare Pages Preview 部署成功。
- 打开测试地址检查页面和功能。
- 确认无误后合并到
main。 - Cloudflare Pages 自动发布正式站点。
- 访问正式域名做最终确认。
这种方式比直接推正式环境更稳,也更适合 AI 辅助开发。AI 可以快速生成修改,但仍然需要通过测试环境确认结果。
用到的开源项目和文档
核心开源项目:
参考过的视觉灵感:
官方文档:
- Hexo 官方文档
- Butterfly 官方文档
- Cloudflare Pages
- Cloudflare DNS
- Cloudflare D1
- Cloudflare Workers AI
- Cloudflare Vectorize
- Resend 文档
- Tavily 文档
当前站点:
成本和限制
这套方案最大的优点是低成本。GitHub、Cloudflare Pages、Cloudflare DNS、D1、Workers AI、Vectorize 和 Resend 都有免费或低成本入口。对于个人 Blog 来说,这已经足够支撑早期使用。
但它也有边界:
- 免费额度不是无限资源。
- 邮件送达率需要慢慢养域名信誉。
- D1 适合轻量数据,不适合复杂后台系统。
- AI 搜索需要索引质量和提示词持续优化。
- 动态背景不能影响文章阅读和低性能设备体验。
- 自动审核不能完全替代人工判断。
所以当前策略是:核心内容保持静态,动态能力只做必要增强;能用简单方案解决,就不急着引入复杂架构。
这次搭建的收获
这次 Blog 搭建最大的变化,不只是做出了一个网站,而是把“个人云端平台”这件事拆成了可迭代的小步骤:
- 先用 GitHub 保存内容和代码。
- 再用 Hexo 生成静态 Blog。
- 再用 Butterfly 快速获得可用的阅读体验。
- 再用 Cloudflare Pages 发布到公网。
- 再绑定自己的域名。
- 再逐步加入评论、订阅、友链、后台、统计、搜索和 AI 能力。
以前觉得“搭一个自己的云端平台”像是一个很大的项目;现在借助 AI 编程工具,可以把它变成一连串可以验证的小任务。
这也是这个 Blog 的初心:用低成本的方式,搭一个自己的学习记录入口;既能沉淀内容,也能不断练习云端、前端、部署、域名、边缘函数和数据服务这些真实技术。
会持续更新,慢,但不停。