选技术栈并搭骨架:第一次提交
为书单项目选定 Astro、Tailwind 和 Cloudflare Workers,让 Claude Code 初始化项目、写好 CLAUDE.md、完成第一次 git 提交并推到 GitHub。
学完这一课,你能
- 能说清这套技术栈每一层为什么这样选
- 能让 Claude Code 初始化 Astro + Tailwind + Cloudflare 项目并验证能构建
- 能写出精简有效的项目 CLAUDE.md,把技术栈和红线固定下来
- 能在提交前检查没有密钥进入仓库,并把代码推到 GitHub
有了规格,下一步是让项目「立起来」:能启动、能构建、有版本管理、代码在远端有备份。这一步看起来平淡,却决定了后面五课的质量。骨架搭歪了,后面每次让智能体改东西,都会在歪的地基上继续歪。
这一课有两个目标:选对栈并把选择固定下来,完成第一次提交。
为什么选这套栈
选技术栈的标准不是「最先进」,而是对一个人维护的小项目最省心。书单项目的需求很朴素:几个页面、一张表、一个调用 AI 的接口。
| 层 | 选择 | 理由 |
|---|---|---|
| 页面 | Astro | 默认输出很少的 JavaScript,内容型页面很快;组件用 .astro 文件,智能体写起来不容易出错 |
| 样式 | Tailwind CSS | 样式写在标签旁边,智能体改一个组件不会牵连全局;设计令牌用 CSS 变量,下一课细讲 |
| 运行环境 | Cloudflare Workers(含静态资源) | 页面和接口放在同一个 Worker 里,一次部署,没有单独的服务器要管 |
| 数据库 | D1 | Cloudflare 托管的 SQLite,免费额度对个人项目足够,用法就是 SQL |
| AI | Workers AI | 在同一个平台里直接调用模型,不需要另外申请密钥 |
| 代码托管与部署 | GitHub + GitHub Actions | 推送即部署,第 6 课配置 |
一个值得单独说的变化是 Workers 与 Pages。早几年部署前端框架到 Cloudflare,大家默认用 Pages。现在 Cloudflare 的框架指南和 Astro 官方部署文档都以 Workers 为准:Workers 可以同时托管静态资源和服务端代码,配置统一写在 wrangler 配置文件里。Astro 的 Cloudflare 适配器在 v13 起已经移除了对 Pages 的支持。所以如果你在网上看到「创建 Pages 项目、连接 Git 仓库」的老教程,不要照着做,以官方当前文档为准。
另一个变化是配置文件格式。Cloudflare 现在推荐新项目使用 wrangler.jsonc(带注释的 JSON),而不是早年的 wrangler.toml。部分较新的功能只在 JSON 格式的配置里提供。
让 Claude Code 搭骨架
骨架搭建是典型的「步骤明确、结果可检查」的任务,很适合交给智能体。但要注意两点:
- 把栈和版本说死。否则它可能顺手选 Next.js,或者用旧的 Pages 配置。
- 让它自己验证。构建通过才算完成,别接受「已创建」这种自述。
整个过程的命令,其实只有这几条(智能体会替你执行,你要能看懂):
# 1. 创建 Astro 项目(交互式,选「空项目/minimal」模板,不要选带示例的)
npm create astro@latest my-shelf
# 2. 添加 Cloudflare 适配器:安装依赖并更新 astro.config.mjs,同时生成 wrangler.jsonc
npx astro add cloudflare
# 3. 添加 Tailwind:安装官方 Vite 插件,并创建 src/styles/global.css
npx astro add tailwind
# 4. 把 wrangler 装成开发依赖,保证团队和 CI 用同一个版本
npm install -D wrangler@latest
如果你是在已有 SPEC.md 的目录里操作,npm create astro@latest 可以用 . 作为目标目录。执行前让智能体先确认目录里只有 SPEC.md。
适配器装好后,wrangler.jsonc 大致是这个形状(以官方文档为参照,实际字段以生成的为准):
{
"name": "my-shelf",
"main": "@astrojs/cloudflare/entrypoints/server",
"compatibility_date": "2026-10-25",
"compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
"assets": {
"binding": "ASSETS",
"directory": "./dist"
},
"observability": { "enabled": true }
}
几个字段的含义:
main是 Worker 的入口,由适配器提供;assets告诉 Wrangler 把构建产物dist目录当静态资源上传;compatibility_date决定运行时行为的版本,填你创建项目当天的日期,之后不要随手改;observability打开 Workers 日志,第 6 课查日志时会用到。
模板自带的 .gitignore 内容以实际生成的为准,不一定覆盖 Cloudflare 相关的本地文件。创建后让智能体确认它至少包含这些:
node_modules/
dist/
.astro/
.wrangler/
.dev.vars*
.env*
.dev.vars 是 Wrangler 约定的本地密钥文件,后面存放管理令牌。它必须在第一次提交之前就被忽略。
写项目的 CLAUDE.md
CLAUDE.md 是 Claude Code 每个会话开头都会读的项目说明。官方的建议是:只写「删掉就会让它犯错」的内容,越短越好。在项目里运行 /init 可以生成一份草稿,再手工收紧。(写法细节见 CLAUDE.md 与记忆。)
书单项目的 CLAUDE.md 可以这样写:
# 个人书单(my-shelf)
规格见 @SPEC.md。需求变化时先改 SPEC.md,再改代码。
## 技术栈(不要替换)
Astro 7(on-demand 渲染)+ Tailwind CSS 4 + Cloudflare Workers(含静态资源)
+ D1(绑定名 DB)+ Workers AI(绑定名 AI)。配置文件用 wrangler.jsonc,不用 Pages。
## 常用命令
- `npm run dev`:本地开发
- `npm run build`:构建,改完代码必须跑通
- `npx wrangler types`:改完 wrangler.jsonc 后重新生成类型
- 数据库迁移:`npx wrangler d1 migrations apply my-shelf-db --local`
## 红线
- 绝不读取、打印或提交 `.dev.vars`、`.env*`;密钥只通过 `wrangler secret` 或环境变量
- 绝不对 `--remote` 的数据库执行写操作,也不执行 `wrangler deploy`,除非我明确要求
- SQL 一律使用 `bind()` 参数绑定,禁止字符串拼接
- 不要用 `set:html` 渲染用户输入
- 不新增 SPEC.md 里「不做什么」列出的功能
这份文件只有二十来行,但每一行都在防一种具体的失误。你会发现它和 .gitignore 是配套的:一个管智能体的行为,一个管仓库里有什么。
CLAUDE.md 只是「提示」,不是强制。如果某条红线你一刻也不想它越过,比如读取 .dev.vars,还要在 .claude/settings.json 里加一条 Read 拒绝规则,让权限系统来拦(见 权限与安全):
{
"permissions": {
"deny": ["Read(./.dev.vars)", "Read(./.env)"]
}
}
第一次提交:先看再提交
提交之前,让智能体做两件事:npm run build 验证骨架能构建,git status 和 git diff --stat 列出将要提交的文件。你要亲眼看一遍这份清单,重点找三类东西:密钥文件、node_modules、dist。这一步在第 6 课也会有,只是那时会交给 CI。
$ git init && git add -A && git status --short A .gitignore A CLAUDE.md A SPEC.md A astro.config.mjs A package.json A package-lock.json A src/pages/index.astro A src/styles/global.css A wrangler.jsonc# 清单里没有 .dev.vars、.env、node_modules、dist,可以提交$ git commit -m "chore: 初始化 Astro + Tailwind + Cloudflare 骨架"$ gh repo create my-shelf --private --source=. --push# 私有仓库创建成功并推送;公开前先想清楚仓库里有没有不该公开的内容 gh repo create 的三个参数分别是:--private 选择私有仓库,--source=. 以当前目录为来源,--push 把已有提交推上去。这条命令会在你的 GitHub 账号下创建仓库,属于外部写入,建议你自己确认后在终端执行,或者在智能体询问时明确点头。
之后的约定也提前说好:每课在一个分支上做,合并前看 diff。直接往 main 推没有硬性禁止,但从现在起养成习惯,第 6 课配置自动部署后,推到 main 就意味着上线。
常见坑
- 智能体换了栈。症状是出现
next.config.js或functions/目录。原因通常是 CLAUDE.md 没写栈,或者写得太含糊。 - 照着旧教程配了 Pages。症状是出现
_routes.json之类的文件,或者适配器版本过旧。让智能体对照上面列的官方页面重做。 compatibility_date被改来改去。它影响运行时行为,应该是一次性设定,除非你有意升级。- 构建能过,运行时才报错。骨架阶段只能证明「编译通过」,数据库和 AI 要到第 4 课才会真正被用到。
读取 SPEC.md,在当前目录搭建项目骨架。技术栈固定为:Astro(最新稳定版)+ Tailwind CSS(用 npx astro add tailwind)+ Cloudflare Workers(用 npx astro add cloudflare),配置文件使用 wrangler.jsonc,不要使用 Cloudflare Pages。
步骤:
- 目录里只有 SPEC.md 时,用
npm create astro@latest .的最小模板初始化;创建过程中不要选择示例内容; - 添加 Cloudflare 适配器和 Tailwind,并安装 wrangler 作为开发依赖;
- 打开 wrangler.jsonc,把 name 改为 my-shelf,确认 main、assets、observability 与 Astro 官方 Cloudflare 部署文档一致,compatibility_date 使用今天的日期;
- 确保 .gitignore 包含 node_modules、dist、.astro、.wrangler、.dev.vars*、.env*;
- 在 package.json 里加一个
"types": "wrangler types"脚本; - 生成 CLAUDE.md:技术栈、常用命令、红线(不碰密钥文件、不对远程数据库写入、不自行部署、SQL 只用参数绑定),控制在 30 行内;
- 运行 npm run build,把结果贴给我。
完成后不要提交。运行 git status,列出所有将被提交的文件,并逐项说明为什么需要它,等我确认后再提交。
下面哪个说法最准确地描述了 Cloudflare 上部署 Astro 的当前推荐做法?
为什么 `.dev.vars` 要在第一次 git 提交之前就加入 .gitignore?
动手任务
动手清单
0/5下一课:做界面。骨架已经有了,我们先用假数据把页面做出来,后端留到第 4 课。
参考来源
- Deploy your Astro site to Cloudflare Workers(Astro 官方文档)
- @astrojs/cloudflare 适配器(Astro 官方文档)
- Install and set up Astro(Astro 官方文档)
- Styling and CSS:添加 Tailwind(Astro 官方文档)
- Astro on Cloudflare Workers(Cloudflare 官方文档)
- Wrangler configuration(Cloudflare 官方文档)
- Manage Claude's memory(Claude Code 官方文档)
- gh repo create(GitHub CLI 官方手册)
工具更新很快,若与官方文档不一致,以官方为准。
学完了吗?
标记完成会记录在本机浏览器,计入你的学习进度和连续天数。