1. 项目缘起与整体思路拆解
1.1 为什么选这个题目:一个周末的极限挑战
先说清楚这个项目到底在做什么。标题里提到的“香港通勝”,是粤港澳地区非常流行的一种传统民俗历书,内容涵盖每日宜忌、节气、生肖运程、吉凶方位等。传统做法是每年年底出一本厚厚的小册子,但年轻一代更习惯在手机上随手查。我当时的想法很简单:能不能用 AI 辅助编程的方式,在一天之内做出一个可用的在线通勝查询站,技术栈锁定 Next.js + Vercel + Cloudflare,开发过程尽量交给 Claude 来驱动。
这里的关键词是vibe coding。这个词最近在开发者圈子里很火,核心意思是你不再逐行手写代码,而是用自然语言描述意图,让 AI 生成大部分实现,你负责把控方向、审查结果、调整细节。它和传统的“复制粘贴 AI 代码”不一样,vibe coding 更强调一种流畅的协作节奏——你提需求,AI 出方案,你反馈,AI 迭代,像和一个很懂技术的搭档边聊边做。
为什么选这个组合?Next.js 负责前端渲染和路由,Vercel 负责一键部署和边缘加速,Cloudflare 负责域名解析和缓存策略。这三者配合起来,基本不需要碰服务器运维,对个人项目来说是最省心的方案。而 Claude 在这个流程里扮演的是“全栈结对程序员”的角色,从数据建模到页面组件再到部署配置,它都能给出可用的初稿。
适合谁来读这篇内容?如果你是有一定前端基础、想尝试 AI 辅助开发流程的开发者,或者你对传统民俗类产品的数字化感兴趣,再或者你只是想看看 vibe coding 在实际项目中到底靠不靠谱,那这篇分享应该能给你一些参考。我不会只讲“怎么装环境”这种基础操作,而是把重点放在决策逻辑、踩坑记录和可复现的步骤上。
1.2 技术选型背后的真实考量
很多人看到 Next.js + Vercel + Cloudflare 这个组合,第一反应是“这不是标配吗”。但我在选型时确实纠结过几个点,这里把思考过程摊开说。
为什么不用纯静态 HTML + 原生 JS?通勝网站的核心功能是日期查询和内容展示,看起来静态就够了。但问题在于,通勝的数据结构比较复杂:每天有宜忌列表、冲煞生肖、吉神方位、五行纳音等多个字段,而且需要根据用户选择的日期动态渲染。如果用纯静态方案,要么预生成 365 个页面,要么用前端框架做客户端渲染。预生成页面在数据更新时很麻烦,客户端渲染又不利于 SEO。Next.js 的 SSG + ISR 刚好解决这个问题:构建时生成页面,后续可以增量更新,兼顾性能和可维护性。
为什么部署选 Vercel 而不是自建服务器?这个项目是个人性质的,没有预算去买云服务器,也不想花时间配置 Nginx 和 SSL 证书。Vercel 的免费额度对个人项目完全够用,而且和 Next.js 是同一家公司出的,兼容性最好。部署流程就是连上 Git 仓库,点几下就完事,后续每次 push 自动触发构建。对于一天上线的目标来说,这是最省时间的路径。
Cloudflare 在这里的角色是什么?主要是域名管理和 CDN 加速。Vercel 本身有全球边缘网络,但如果你想让自定义域名走 Cloudflare 的解析和缓存,可以做一些额外的优化。比如设置页面缓存规则、压缩图片、开启 Brotli 压缩等。另外 Cloudflare 的 DNS 解析速度很快,对国内访问体验有一定改善。不过要注意,Vercel 和 Cloudflare 的代理层如果配置不当,可能会出现 SSL 证书冲突或缓存不一致的问题,后面我会详细说怎么处理。
Claude 在哪个环节介入?整个开发流程中,Claude 主要承担四类工作:一是根据我的自然语言描述生成 Next.js 页面组件和 API 路由;二是帮我设计通勝数据的 JSON 结构;三是生成部署配置文件和 Cloudflare 的缓存规则;四是在遇到报错时帮我分析原因并给出修复方案。我用的方式是 Claude 的对话界面配合代码块输出,没有用更复杂的 Agent 工具链,因为项目规模不大,直接对话效率更高。
2. 核心细节解析与实操要点
2.1 通勝数据结构的设计与 AI 协作方式
通勝的数据是整个项目的基础。如果数据结构设计得不好,后面页面渲染和查询逻辑都会很痛苦。我先让 Claude 帮我梳理了一份典型通勝日课包含的字段,然后根据实际展示需求做了裁剪。
一份完整的通勝日课通常包含以下信息:公历日期、农历日期、干支纪年、生肖、节气、宜做的事、忌做的事、冲煞生肖、吉神方位、凶神方位、五行纳音、彭祖百忌、胎神方位等。对于在线查询站来说,我保留了最常用的几个字段:公历日期、农历日期、宜、忌、冲、煞、吉神、凶神、五行。这样既不会让页面太拥挤,也覆盖了用户最关心的内容。
数据结构用 JSON 来组织,每天一条记录,放在一个数组里。Claude 建议我用以下格式:
{ "date": "2025-01-01", "lunar": "腊月初二", "ganzhi": "甲辰年 丙子月 庚午日", "zodiac": "龙", "yi": ["祭祀", "祈福", "出行"], "ji": ["动土", "安葬"], "chong": "鼠", "sha": "北", "jishen": ["天德", "月德"], "xiongsha": ["岁破", "月破"], "wuxing": "路旁土" }这个结构的好处是字段清晰,前端渲染时直接映射即可。Claude 还提醒我,宜忌列表的长度不固定,有的日子宜项很多,有的很少,所以用数组而不是固定字段。另外,冲煞信息可以拆成“冲”和“煞”两个字段,方便单独展示。
注意:通勝数据涉及传统民俗内容,不同流派和地区的算法可能有差异。我这里的做法是参考公开的通用历法数据,不涉及任何特定宗教或政治立场,仅作为传统文化展示。
数据来源方面,我没有用爬虫去抓取现有网站,而是让 Claude 根据公开的历法规则生成了一份 2025 年的示例数据。这里要说明的是,AI 生成的历法数据可能存在误差,尤其是干支和宜忌部分。我的处理方式是:先用 AI 生成初稿,然后人工抽查了几个重要节气日期的数据,确认基本合理后作为演示数据使用。如果要做正式产品,建议接入专业的历法计算库或人工校对的数据源。
2.2 Next.js 页面架构与组件拆分
Next.js 的 App Router 是我这次用的路由方案。相比 Pages Router,App Router 对服务端组件的支持更好,而且布局嵌套更直观。整个网站的页面结构很简单:首页展示今日通勝,日期选择页可以查任意日期,关于页放一些说明。
首页的实现思路是:服务端组件读取当天的数据,渲染成卡片式布局。Claude 帮我生成了初版的page.tsx,核心逻辑是引入数据文件,根据当前日期筛选对应记录,然后传给展示组件。这里有个细节需要注意:服务端组件不能直接用useState或useEffect,所以日期选择功能要单独拆成客户端组件。
我让 Claude 把组件拆成了三个部分:TungShingCard负责展示单日通勝内容,DatePicker负责日期选择交互,Layout负责全局导航和页脚。这样拆分的好处是职责清晰,后续修改某个部分不会影响其他部分。Claude 在生成组件时还主动加了 TypeScript 类型定义,虽然我一开始没要求,但后来发现这对维护很有帮助,尤其是字段较多的时候,类型提示能避免拼写错误。
样式方面,我没有用 Tailwind CSS,而是用了 CSS Modules。原因是我对 Tailwind 的类名堆叠不太习惯,而且这个项目的样式不复杂,手写 CSS 更可控。Claude 一开始默认生成了 Tailwind 的类名,我明确告诉它改用 CSS Modules 后,它很快就调整过来了。这也说明 vibe coding 的关键在于及时反馈:AI 不知道你的偏好,你得主动说。
2.3 Vercel 部署配置与 Cloudflare 接入细节
Vercel 的部署流程本身很简单,但有几个配置点容易忽略。首先是在项目根目录创建vercel.json,用来定义构建命令和路由规则。Claude 帮我生成的配置如下:
{ "buildCommand": "next build", "outputDirectory": ".next", "framework": "nextjs", "regions": ["hkg1"] }regions字段指定了部署区域为香港,这样对粤港澳地区的用户访问速度会更快。Vercel 的边缘网络会自动处理全球分发,但指定主要区域可以减少冷启动延迟。
Cloudflare 的接入分两步:一是把域名的 NS 记录指向 Cloudflare,二是在 Vercel 后台添加自定义域名。这里有个坑:如果 Cloudflare 的代理状态是“已代理”(橙色云朵),Vercel 的 SSL 证书验证可能会失败。我的做法是先在 Cloudflare 把 DNS 记录设为“仅 DNS”(灰色云朵),等 Vercel 签发证书后再改回“已代理”。这样既能用 Cloudflare 的 CDN,又不会影响证书签发。
缓存策略方面,我在 Cloudflare 设置了两条规则:一是对/_next/static/*路径设置长期缓存,因为 Next.js 的静态资源带哈希指纹,内容变了文件名也会变;二是对 API 路由设置不缓存,保证数据实时性。Claude 提醒我,Cloudflare 的缓存规则优先级要设置正确,否则可能覆盖 Vercel 本身的缓存头。
提示:Vercel 和 Cloudflare 同时开启代理时,可能会出现“双重 CDN”的情况,导致缓存更新延迟。我的经验是,静态资源交给 Cloudflare 缓存,动态内容交给 Vercel 的边缘函数处理,两者分工明确就不会冲突。
3. 实操过程与核心环节实现
3.1 从零搭建项目骨架的完整命令记录
这一节我把实际操作的命令和步骤完整记录下来,你可以直接照着做。前提是你本地已经装了 Node.js 18 以上版本和 Git。
第一步,创建 Next.js 项目。我用的命令是:
npx create-next-app@latest tung-shing --typescript --app --no-tailwind --no-eslint --src-dir这里我关掉了 Tailwind 和 ESLint,因为项目小,不需要额外的配置复杂度。--src-dir把代码放在src目录下,结构更清晰。创建完成后进入项目目录:
cd tung-shing第二步,安装必要的依赖。除了 Next.js 自带的包,我还加了date-fns用来处理日期格式化:
npm install date-fns第三步,创建数据文件。在src/data目录下新建tungshing-2025.json,把之前设计好的 JSON 数据放进去。数据量不大,2025 年全年 365 条记录,文件大小约 200KB,直接打包进构建产物没问题。
第四步,编写页面组件。我让 Claude 生成了src/app/page.tsx的初版代码,核心逻辑是:
import tungshingData from '@/data/tungshing-2025.json'; import TungShingCard from '@/components/TungShingCard'; import DatePicker from '@/components/DatePicker'; export default function Home() { const today = new Date().toISOString().split('T')[0]; const todayData = tungshingData.find(item => item.date === today); return ( <main> <h1>今日通勝</h1> {todayData ? <TungShingCard data={todayData} /> : <p>暂无数据</p>} <DatePicker /> </main> ); }这段代码的逻辑很直白:找到今天对应的数据,传给卡片组件渲染。如果没有找到,显示提示信息。Claude 还建议我加一个generateStaticParams函数来预生成所有日期的页面,但我觉得当前需求不需要,就跳过了。
第五步,本地测试。运行npm run dev,打开http://localhost:3000,检查页面是否正常渲染。我第一次运行时遇到了一个报错:Cannot find module '@/data/tungshing-2025.json'。原因是 TypeScript 默认不支持直接导入 JSON 文件,需要在tsconfig.json里开启resolveJsonModule。Claude 帮我定位了这个问题,并给出了修改方案:
{ "compilerOptions": { "resolveJsonModule": true, "esModuleInterop": true } }改完之后重新运行,页面正常显示了。这个过程让我意识到,vibe coding 虽然能加速开发,但基础的配置问题还是需要自己理解,否则 AI 给的方案你可能不知道怎么调。
3.2 日期选择功能的实现与交互优化
日期选择是通勝网站的核心交互。用户选一个日期,页面展示那天的宜忌信息。我一开始想用原生<input type="date">,简单直接。但 Claude 提醒我,原生日期选择器在移动端的体验参差不齐,而且样式不好统一。它建议我用一个自定义的下拉选择器,按月分组展示日期。
我采纳了这个建议,让 Claude 生成了一个DatePicker组件。核心逻辑是用useState管理选中的日期,用useEffect在日期变化时更新展示内容。这里有个细节:因为首页是服务端组件,DatePicker必须标记为'use client',否则不能用 React 的钩子。
'use client'; import { useState } from 'react'; import tungshingData from '@/data/tungshing-2025.json'; import TungShingCard from './TungShingCard'; export default function DatePicker() { const [selectedDate, setSelectedDate] = useState(''); const selectedData = tungshingData.find(item => item.date === selectedDate); return ( <div> <select onChange={(e) => setSelectedDate(e.target.value)} value={selectedDate}> <option value="">选择日期</option> {tungshingData.map(item => ( <option key={item.date} value={item.date}>{item.date}({item.lunar})</option> ))} </select> {selectedData && <TungShingCard data={selectedData} />} </div> ); }这个实现虽然简单,但有个性能问题:每次选择日期都会重新渲染整个列表。对于 365 条数据来说影响不大,但如果数据量更大,就需要做虚拟滚动或分页。Claude 建议我后续可以用react-window来优化,但当前阶段没必要过度设计。
交互优化方面,我加了一个小功能:默认选中今天,这样用户打开页面就能直接看到今日通勝,不需要额外操作。实现方式是在useState的初始值里计算今天的日期:
const today = new Date().toISOString().split('T')[0]; const [selectedDate, setSelectedDate] = useState(today);这个改动虽然小,但用户体验提升很明显。Claude 在生成代码时没有主动加这个逻辑,是我后来想到的。这也说明 vibe coding 不是完全放手,你仍然需要从产品角度思考。
3.3 部署上线与域名配置的实操记录
本地开发完成后,部署到 Vercel 的流程如下。首先把代码推到 GitHub 仓库:
git init git add . git commit -m "initial commit" git remote add origin <你的仓库地址> git push -u origin main然后在 Vercel 官网用 GitHub 账号登录,点击“New Project”,选择刚才的仓库,Vercel 会自动识别 Next.js 项目并填充构建配置。点击“Deploy”后等待一两分钟,构建完成会分配一个*.vercel.app的临时域名。
接下来配置自定义域名。我在 Cloudflare 上买了一个域名,然后在 Vercel 项目的“Domains”设置里添加这个域名。Vercel 会给出两条 DNS 记录:一条 A 记录指向76.76.21.21,一条 CNAME 记录指向cname.vercel-dns.com。我把这两条记录添加到 Cloudflare 的 DNS 管理页面。
这里的关键操作是:先把 Cloudflare 的代理状态设为“仅 DNS”,等 Vercel 显示域名验证通过、SSL 证书签发完成后,再把代理状态改回“已代理”。如果不这样做,Vercel 的证书验证会一直卡在“Pending”状态。我第一次配置时不知道这个细节,等了半小时才发现问题,后来在 Claude 的提示下才解决。
证书签发完成后,在 Cloudflare 的 SSL/TLS 设置里把加密模式设为“Full (Strict)”,这样 Cloudflare 到 Vercel 之间的连接也是加密的。另外开启“Always Use HTTPS”和“Automatic HTTPS Rewrites”,确保所有请求都走 HTTPS。
注意:Cloudflare 的“Rocket Loader”功能建议关闭,它可能会和 Next.js 的脚本加载策略冲突,导致页面白屏或交互失效。我在测试时遇到过这个问题,关掉之后就正常了。
4. 常见问题与排查技巧实录
4.1 构建失败与依赖冲突的排查思路
在部署过程中,我遇到了几次构建失败。最常见的是依赖版本冲突。比如date-fns的某个版本和 Next.js 内置的日期处理库有类型定义冲突,导致 TypeScript 编译报错。排查方法是看 Vercel 的构建日志,找到报错的具体文件和行号,然后让 Claude 分析原因。
Claude 给出的建议是:锁定依赖版本,避免使用^或~这样的范围版本号。在package.json里把date-fns的版本固定为3.6.0,重新安装后问题解决。这个经验告诉我,AI 辅助开发虽然快,但依赖管理这种基础工作还是需要自己上心。
另一个常见问题是环境变量缺失。Vercel 的构建环境是独立的,本地能跑的代码不一定能在 Vercel 上跑。比如我在本地用了.env.local文件存放一些配置,但忘记在 Vercel 后台添加对应的环境变量,导致构建时读取不到。解决方法是:在 Vercel 项目的“Settings > Environment Variables”里逐条添加,然后重新部署。
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 构建时报模块找不到 | 依赖未安装或路径错误 | 检查构建日志中的模块名 | 确认package.json中有该依赖,检查导入路径大小写 |
| TypeScript 类型报错 | 类型定义缺失或冲突 | 查看报错文件和行号 | 安装@types/包或调整tsconfig.json |
| 页面白屏 | 客户端组件报错 | 打开浏览器控制台看报错 | 检查'use client'标记和钩子使用 |
| 域名验证失败 | DNS 记录未生效或代理冲突 | 用dig命令检查 DNS 解析 | 先关闭 Cloudflare 代理,等验证通过再开启 |
| 样式不生效 | CSS Modules 导入错误 | 检查类名是否匹配 | 确认导入语句和类名拼写一致 |
4.2 AI 生成代码的审查要点与修正技巧
vibe coding 最大的风险是盲目信任 AI 生成的代码。我在这个项目里总结了几个审查要点,分享给你。
第一,检查边界条件。Claude 生成的日期筛选逻辑用的是find方法,如果找不到对应日期会返回undefined。我在代码里加了空值判断,避免页面崩溃。AI 通常不会主动处理所有边界情况,你需要自己补上。
第二,验证数据格式。Claude 生成的 JSON 数据结构虽然合理,但字段命名风格不统一,有的用驼峰有的用下划线。我统一改成了驼峰命名,保持一致性。另外,宜忌列表里的项目可能有重复,我加了一个去重逻辑。
第三,检查性能隐患。首页的服务端组件每次请求都会读取整个 JSON 文件并执行find。对于 365 条数据来说没问题,但如果数据量增长到几千条,就需要考虑用数据库或索引优化。Claude 在生成代码时不会主动考虑这些,你得根据实际场景判断。
第四,确认安全配置。Next.js 的 API 路由默认没有速率限制,如果暴露在公网可能被滥用。我在 Vercel 的vercel.json里加了一条简单的速率限制规则,虽然不完美,但能挡住大部分异常请求。
提示:每次让 Claude 生成代码后,花两分钟快速过一遍逻辑,重点看条件判断、循环边界和错误处理。这比事后调试省时间得多。
4.3 上线后的监控与迭代建议
网站上线后,我在 Vercel 后台开启了 Analytics,可以看到每天的访问量和页面性能数据。另外在 Cloudflare 开启了 Web Analytics,两者数据可以互相印证。上线第一天的访问量不大,但有几个用户反馈说日期选择器的下拉列表太长,滚动不方便。
根据反馈,我让 Claude 帮我改成了按月分组的折叠面板。实现方式是用<details>和<summary>标签,配合 CSS 做样式。这个改动花了不到半小时,但体验提升很明显。这也说明 vibe coding 的优势在于快速迭代:你有一个想法,AI 帮你实现,你测试后反馈,AI 再调整,循环周期很短。
后续如果要继续完善,我考虑加两个功能:一是支持农历日期查询,用户输入农历日期也能找到对应的通勝信息;二是加一个分享功能,把某天的通勝生成一张图片,方便分享到社交平台。这两个功能都可以让 Claude 先生成初版,我再根据实际效果调整。
5. 个人实操心得与避坑清单
5.1 关于 vibe coding 节奏控制的真实体会
用 Claude 做 vibe coding,最大的感受是节奏很重要。如果你一次性给 AI 太多需求,它生成的代码往往顾此失彼;如果你每次只提一个小需求,来回对话的次数又太多。我的经验是:按功能模块拆分,每个模块的对话控制在三到五轮以内。
比如做日期选择器时,第一轮我让 Claude 生成基础的下拉选择组件,第二轮我提出要默认选中今天,第三轮我要求改成按月分组。每轮只改一个点,AI 的输出质量明显更高。如果我把这三个需求一次性提出来,Claude 可能会在某个细节上理解偏差,导致整体返工。
另外,及时保存可用的版本也很关键。我在项目目录里用 Git 做了多次提交,每次 Claude 生成一个可用的版本就提交一次。这样如果后续改动出了问题,可以快速回滚到上一个稳定版本。AI 生成的代码有时候会引入意想不到的 bug,有版本管理兜底会安心很多。
5.2 技术选型的取舍与后续扩展方向
回头看这个项目,Next.js + Vercel + Cloudflare 的组合确实适合快速上线。但如果要长期运营,有几个点需要考虑。
数据更新方面,目前是硬编码在 JSON 文件里,每年需要手动更新。如果要做成持续运营的产品,建议接入数据库或 CMS,让非技术人员也能更新内容。Next.js 支持多种数据源,切换成本不高。
性能方面,当前所有数据打包在一个 JSON 文件里,首屏加载会包含全年数据。虽然文件不大,但可以优化成按需加载:用户选择月份时再请求对应数据。这需要把数据拆分成多个文件,或者用 API 路由动态返回。
国际化方面,通勝的内容主要是中文,但如果想覆盖更多用户,可以考虑加英文翻译。Next.js 的 i18n 功能可以支持多语言路由,Claude 也能帮忙生成翻译文案。
最后分享一个小技巧:如果你也想用 Claude 做类似的项目,建议在对话开始时先给 AI 一个清晰的上下文,比如“我要做一个 Next.js 项目,用 App Router,样式用 CSS Modules,数据存在本地 JSON 文件里”。这样 Claude 生成的代码会更贴合你的技术栈,减少后续调整的工作量。我在项目初期没做这一步,导致 Claude 默认生成了 Tailwind 的类名,后来花时间改了一轮。提前说清楚,能省不少事。