本站是怎么搭起来的:Astro 7 双语博客 + Cloudflare Pages

AstroCloudflare Pagesi18n建站DeepSeek Harness

这篇文章记录 HarnessDo.com 从零到上线的过程——由 DeepSeek Harness 搭建部署,我负责决策与验收。既是给自己的备忘,也希望能给想搭同样结构博客的人一点参考。

谁搭的:DeepSeek Harness 与我

这个站点的代码、部署、排障几乎全部由 DeepSeek Harness(DSH)完成——一个 AI 编码代理。我作为人,负责做决定、提供账号与凭证、并在每轮完成后验收和纠偏。把双方分工摊开,既是记录,也方便理解“AI 代理到底替人做了哪些事”。

DeepSeek Harness 做的

  • 从零搭建 Astro 7 双语项目:配置文件、i18n 路由、内容集合 schema、布局/组件/样式
  • 修复环境问题:npm/pnpm 缓存 EPERM、Astro 遥测沙箱拦截
  • 设计双语内容集合,并修复中英同 slug 的 id 冲突 bug
  • 撰写首批中英双语文章初稿
  • 本地构建、预览、逐路由验证
  • 创建 Cloudflare Pages 项目并部署上线
  • 用 RDAP/DNS 核查域名归属(发现 harnessgo.com 与 harnessdo.com 的出入)
  • 全站改名 harnessgo → harnessdo(含工作目录、Pages 项目)
  • 挂载自定义域名、创建 CNAME、跟进 SSL 签发直到 https 可访问
  • 给 DSH 自身安装 Cloudflare skills 与 MCP 服务器,并重启服务
  • 品牌改名 HarnessDo.com(读者可见文案)并重新部署
  • Git 初始化与首次提交

我(人)做的

  • 注册域名(harnessdo.com,Cloudflare)
  • 技术选型拍板:Astro、中英双语、部署到 Cloudflare Pages
  • 在浏览器完成 Cloudflare OAuth 授权
  • 创建并配置 Cloudflare API Token(含 DNS 编辑权限)
  • 逐轮纠偏:确认域名是 harnessdo、要求全部改名 harnessdo、品牌用 HarnessDo
  • 提供启动命令并确认重启 DSH
  • 之后:持续写文章、审阅内容、维护站点

一句话:DSH 承担了几乎全部“动手执行”,我承担了“决策、授权、验收”——这正是本博客要追踪的 DeepSeek Harness 的日常用法之一。

技术选型

需求 选择 理由
静态站点框架 Astro 为内容型网站设计,Markdown 一等公民,输出纯静态页面,零 JS 默认
托管 Cloudflare Pages 免费、全球 CDN、与域名同账户、免备案
写作语言 Markdown 内容集合 + schema 校验,长期维护成本最低

选 Astro 而不是 Next.js 或 Hugo,核心原因是内容模型:Astro 的内容集合(content collections)自带 schema 校验,写错了 frontmatter 构建直接报错,这对一个要长期更新、跨中英双语的博客非常重要。

项目结构

HarnessDo.com/
├── astro.config.mjs          # site 配置 + sitemap 集成
├── src/
│   ├── content.config.ts     # 内容集合 schema(Astro 5+ 的写法)
│   ├── content/blog/
│   │   ├── zh/*.md           # 中文文章
│   │   └── en/*.md           # 英文文章
│   ├── i18n/ui.ts            # 中英文案字典
│   ├── layouts/              # Base / PostLayout
│   ├── components/           # Header / Footer
│   └── pages/
│       ├── index.astro       # 根路径,按浏览器语言跳转
│       ├── [lang]/           # /zh/ /en/ 首页
│       │   ├── blog/         # 文章列表 + [...slug] 文章页
│       │   ├── about.astro
│       │   └── rss.xml.ts    # 每语言一个 RSS
│       └── 404.astro
└── public/                   # favicon、robots.txt

双语怎么做

  • 路由是 /zh/.../en/...,根路径 / 根据浏览器 navigator.language 客户端跳转(默认中文)。
  • 文章用同一个 slug 写两份,src/content/blog/zh/<slug>.mdsrc/content/blog/en/<slug>.md,frontmatter 里声明 lang
  • 内容集合里每份文件的 id 保留语言前缀(如 zh/2025-08-15-welcome),避免中英同 slug 冲突;URL 里的 slug 在路由层剥离前缀(src/lib/posts.tsslugOf)。
  • 页面文案(导航、按钮、关于页)放在 src/i18n/ui.ts 字典里,按 lang 取用。

部署

构建产物是 dist/,用 wrangler 推送到 Cloudflare Pages:

pnpm build
wrangler pages deploy dist --project-name=harnessdo

域名绑定:Cloudflare 控制台 → Pages → 项目 → Custom domains 添加 HarnessDo.com,再在 DNS 里加一条 CNAME(@harnessdo.pages.dev,Proxied)。域名注册在 Cloudflare,无需备案。

以后怎么发新文章

  1. src/content/blog/zh/<日期>-<slug>.md,英文版写到 en/,两份文件的 slug 保持一致。
  2. frontmatter 必填:langtitledescriptionpubDate;可选 tagsdraftdshVersionseries
  3. 本地预览:pnpm dev,然后 pnpm build && wrangler pages deploy dist --project-name=harnessdo 上线。

内容 schema 在 src/content.config.ts 里,加字段也在这里改。

踩过的坑

  • npm 缓存目录损坏。 这台机器上 ~/.npm 缓存有 root 所有权的文件,npm 直接 EPERM。解决:项目里 .npmrccache 指到项目目录,命令里用 npm_config_cache 覆盖环境变量(环境变量优先级高于项目配置)。
  • pnpm 的 dlx 缓存也在家目录。 pnpm create astro 的临时缓存同样被沙箱拦了,干脆手写全部文件,反而更清楚每一处配置在干什么。

以上。接下来就该写正文了。

← 返回博客