本文是一份可逐步操作的教程,目标是让你用 Astro + Fuwari 主题搭建一个个人静态博客,并通过 GitHub 托管、Cloudflare Pages 自动部署上线,最终绑定你自己的域名。
本文面向有编程基础、会用终端、了解 git 和 npm/pnpm 的读者。示例命令会同时标注 Windows(PowerShell)与 macOS/Linux 的差异。
前置条件(先读完,再动手)
在开始之前,请确认下面这些前置条件都已满足。它们之间有先后依赖,缺一个都会卡在后面的步骤上,所以先逐一核对:
| 前置条件 | 为什么需要 | 检查方式 |
|---|---|---|
| GitHub 账号 | 代码托管,Cloudflare Pages 从这里拉取源码并自动构建 | 能登录 github.com |
| Cloudflare 账号 | 部署与托管静态站点 | 能登录 dash.cloudflare.com |
| Node.js 版本 ≥ 20 | Astro 构建运行环境 | 终端执行 node -v |
| pnpm(通过 corepack 启用) | 本项目官方使用 pnpm 作为包管理器 | 终端执行 pnpm -v |
| 一个域名(可选,本教程会用到) | 绑定自定义网址,替换默认的 xxx.pages.dev | 已购买并可在注册商处修改 DNS |
| 一个本地代码编辑器 | 编辑配置与 Markdown 文章 | VS Code 等任意编辑器均可 |
如果你还没有 Node 环境:请先到 nodejs.org 安装 LTS 版本(≥ 20)。安装完成后,终端里
node -v和npm -v都应能正常输出版本号。
启用 pnpm
本项目要求使用 pnpm。现代 Node 自带 corepack,可以用它来启用 pnpm。在终端执行:
# Windows (PowerShell) / macOS / Linux 通用corepack enablecorepack prepare pnpm@latest --activate执行后运行 pnpm -v,能看到版本号即表示成功。
为什么不直接用 npm?Fuwari 官方的
package.json中声明了packageManager: [email protected],并带有preinstall: npx only-allow pnpm钩子,强制使用 pnpm 以避免锁文件不一致带来的问题。
阶段一:搭建最小可运行博客
这一阶段的目标是先跑通核心链路:初始化项目 → 本地预览 → 推到 GitHub → 部署上线。先得到一个能访问的博客,再谈定制。
1. 用 Fuwari 模板初始化项目
在你想存放项目的目录下,执行 create 命令:
# Windows (PowerShell)npm exec --yes -- create-fuwari@latest my-blog# macOS / Linuxpnpm create fuwari@latest my-blog
npm exec --yes -- create-fuwari@latest与pnpm create fuwari@latest效果一致,都会调用官方的 create 脚手架并生成一个名为my-blog的目录。如果你的终端对某个命令报错,换另一种即可。
命令执行后会询问几个初始化选项(是否初始化 git、是否安装依赖等),按提示选择即可。A: 交互式询问会让你选 TypeScript 类型、是否安装依赖等,全部选默认(Enter)即可。
进入项目目录并安装依赖:
cd my-blogpnpm install依赖安装完成后,项目结构类似:
my-blog/├── src/│ ├── config.ts # 站点配置(标题、头像、导航等)│ ├── content/│ │ └── posts/ # 博客文章存放处│ ├── layouts/│ └── pages/├── astro.config.mjs # Astro 与部署配置├── package.json└── pnpm-lock.yaml2. 本地预览
启动开发服务器:
pnpm dev终端会输出本地地址,通常是 http://localhost:4321。用浏览器打开,你应该能看到 Fuwari 的默认样式的博客首页。
开发服务器会热更新:修改代码或文章后,浏览器自动刷新,无需手动重启。
3. 修改站点配置
先改最基础的站点信息,确认配置链路是通的。打开 src/config.ts,找到 siteConfig 部分:
export const siteConfig: SiteConfig = { title: "我的博客", subtitle: "记录技术与生活", lang: "zh_CN", // ...};把 title 和 subtitle 换成你自己的,保存后回到浏览器,首页标题应已变化。
src/config.ts是 Fuwari 最主要的配置文件,相当于其它静态博客(如 Hexo)里的_config.yml,站点标题、头像、导航、社交链接、主题色等都在这里设置。这一阶段先只改标题,其余后面再慢慢调。
4. 推送到 GitHub
在 GitHub 上新建一个仓库(考虑到博客资源属于个人,建议使用私有仓库,Cloudflare Pages 支持私有仓库的访问)。
回到项目目录,初始化并推送:
git initgit add .git commit -m "init: astro fuwari blog"git branch -M maingit remote add origin https://github.com/YOUR_NAME/my-blog.gitgit push -u origin main把
YOUR_NAME替换成你的 GitHub 用户名,my-blog替换成你的仓库名。此时推送的是源码,不是构建产物,所以不用担心仓库体积。
5. 连接 Cloudflare Pages 并部署
- 登录 Cloudflare 控制台。
- 进入左侧 计算 / Workers & Pages。
- 点击 Create application → 选择 Pages 标签页 → Connect to Git。
- 授权 GitHub,并选择你刚才推送的
my-blog仓库,建议按最小权限规则,仅允许Cloudflare访问勾选的项目,后续想要更改权限的时候访问这个链接。 - 在构建配置中填写:
| 配置项 | 值 |
|---|---|
| Framework preset | Astro |
| Production branch | main |
| Build command | pnpm build |
| Build output directory | dist |
- 点击 Save and Deploy。
Cloudflare 会依次执行:拉取源码 → 安装 pnpm 依赖 → pnpm build → 发布 dist。
为什么构建命令是
pnpm build、输出目录是dist?Fuwari 的package.json里build脚本是astro build && pagefind --site dist(其中 pagefind 是内置的静态搜索,下一阶段会讲),产物统一输出到dist目录,所以这里要填dist。
部署完成后,Cloudflare 会给你一个临时地址,形如:
https://my-blog-xxx.pages.dev打开它,你就能看到一个已上线的博客。至此,最小可运行链路已打通。
阶段二:发布第一篇文章
上线后再验证一次写作 → 自动部署的完整闭环。
1. 理解 Frontmatter
每篇文章都是一个 Markdown 文件,开头有一段 YAML 格式的 frontmatter 描述元信息。Fuwari 使用以下字段(以 src/content/config.ts 中的 schema 为准):
---title: 我的第一篇文章published: 2026-09-07description: 文章摘要tags: - Astrocategory: 技术draft: false---字段说明:
title:文章标题(必填)。published:发布日期(必填),用YYYY-MM-DD格式。description:文章摘要,可选。tags:标签,字符串数组。category:分类,单个字符串(不是数组)。draft:true表示草稿,生产构建不展示;写好后改成false。
2. 写一篇文章
在 src/content/posts/ 下新建一个 Markdown 文件,例如 hello.md,填入 frontmatter 和正文:
---title: 你好,世界published: 2026-09-07tags: - 测试category: 日常draft: false---
这是我的第一篇博客文章。
## 小标题
正文内容,支持标准 Markdown 语法。本地 pnpm dev 下应该能立刻在首页看到这篇文章。
3. 图片路径
如果文章中要用本地图片,推荐把图片放在文章的同名目录下,正文用相对路径引用:
即 src/content/posts/hello/ 下放 cover.png。这样 Astro 会自动处理图片路径,部署后也不会失效。
避免使用磁盘上的绝对路径(如
C:\Users\...或D:\...),否则部署后图片会 404。
4. 提交并自动部署
git add .git commit -m "post: hello world"git push推送到 main 后,Cloudflare Pages 会自动重新构建并发布。等构建完成后刷新你的 pages.dev 地址,就能看到新文章。
阶段三:绑定自定义域名
默认的 xxx.pages.dev 免费域名够用,但如果你有自己的域名,建议绑定,让博客看起来更正式。
1. 在 DNS 中添加记录
假设你的域名是 example.com,博客想挂在 blog.example.com。
场景 A:域名已托管在 Cloudflare(推荐)
如果你的域名已经通过 Cloudflare 管理 DNS(即域名的 Nameserver 已指向 Cloudflare),在 Pages 项目里添加自定义域名时,Cloudflare 通常会自动创建 DNS 记录,无需手动操作。
场景 B:域名托管在其它注册商
需要在你的域名注册商(如阿里云、腾讯云、GoDaddy 等)的 DNS 管理里,手动添加一条记录:
| 类型 | 名称 | 内容 | 代理状态 |
|---|---|---|---|
| CNAME | blog | my-blog.pages.dev | 关闭(或按需) |
若域名完全托管在 Cloudflare,把 Nameserver 改成 Cloudflare 提供的即可,之后 DNS 记录可在 Cloudflare 内统一管理,并开启橙色云朵(代理)以获得 CDN 加速。
2. 在 Pages 项目中添加自定义域名
- 进入你的 Pages 项目 → Custom domains → Set up a custom domain。
- 输入
blog.example.com,点击继续。 - 按 Cloudflare 的提示完成验证。
等待几分钟,Cloudflare 会自动为该域名签发 HTTPS 证书。
3. 修改 astro.config.mjs 的 site
打开 astro.config.mjs,把 site 改成你的正式域名:
export default defineConfig({ site: "https://blog.example.com/", base: "/", trailingSlash: "always", // ...});为什么必须改
site?它会影响到 Sitemap、RSS/Atom 的地址、canonical URL、Open Graph 等,如果还留着默认的演示地址,搜索引擎和订阅源会指向错误的位置。
改完后提交推送,重新部署。之后访问 https://blog.example.com/ 即可。
阶段四:静态搜索(Pagefind)
Fuwari 内置了 Pagefind 静态搜索。它是在构建阶段生成搜索索引的,不需要数据库或后端服务,完全符合静态博客的定位。
它已经默认启用了
看 package.json 的 build 脚本:
"build": "astro build && pagefind --site dist"每次 pnpm build 时,会在 dist 下生成搜索索引。部署到 Cloudflare Pages 后,页面上方导航栏的搜索框即可使用。
本地验证搜索
pnpm buildpnpm previewpnpm preview 会预览 dist 目录。打开预览地址,点导航栏的搜索框,输入文章标题中的关键词,应能搜到结果。
为什么本地
pnpm dev下搜索可能不生效?因为 Pagefind 的索引是构建时生成的,开发模式不会运行pagefind命令。要验证搜索,请用build + preview,而不是dev。
常见问题
Q:corepack enable 或 pnpm 命令报错?
确认 Node 版本 ≥ 20,并已正确启用 corepack。也可以直接 npm install -g pnpm 全局安装。
Q:Cloudflare 构建失败,提示找不到 pnpm?
在 Pages 项目的环境变量中添加 NODE_VERSION=22,并确认构建命令是 pnpm build。Cloudflare 通常能根据 packageManager 字段自动识别,若不能,可把构建命令改为 corepack enable && pnpm install --frozen-lockfile && pnpm build。
Q:文章没出现在首页?
检查 frontmatter 里 draft 是否为 false,以及 published 字段格式是否正确。
Q:图片部署后 404?
确认正文里用的是相对路径(./xxx/xxx.png),且图片确实放在对应目录下。
版本与时效声明
本文基于以下版本编写,若你操作时界面或命令与我描述的不一致,请以官方最新文档为准:
- Astro:5.x(本文基于 5.13.10)
- Fuwari:以 saicaca/fuwari 官方仓库为准
- 包管理器:pnpm 9.x
更新日期:2026-09-07