3个真实项目带你玩转Claude Code:从0到部署
看了那么多介绍和教程,不如直接上手干几个真实项目。这篇文章会带你用Claude Code完成3个从0到部署的完整项目,涵盖前端、后端、全栈场景,每个项目都是真实可用的产品。
不讲空话,直接看操作。
项目1:待办事项API(30分钟完成后端服务)
项目目标
搭建一个生产可用的RESTful API服务,包含:
- 用户认证(JWT)
- CRUD接口
- 数据库集成(PostgreSQL)
- 输入验证
- 错误处理
- API文档
- Docker部署
第一步:初始化项目(5分钟)
对话记录:
diff
你:"创建一个Node.js API项目,使用:
- Express框架
- TypeScript
- Prisma ORM(PostgreSQL)
- Zod验证
- JWT认证
- 项目名:todo-api"
Claude Code:
✓ 创建项目目录结构
✓ 初始化package.json
✓ 配置TypeScript
✓ 安装所有依赖
✓ 创建基础文件结构
生成的项目结构:
bash
todo-api/
├── src/
│ ├── index.ts # 入口文件
│ ├── routes/ # 路由
│ ├── controllers/ # 控制器
│ ├── middleware/ # 中间件
│ └── types/ # 类型定义
├── prisma/
│ └── schema.prisma # 数据库模型
├── tests/ # 测试文件
├── .env.example # 环境变量模板
├── tsconfig.json # TS配置
├── Dockerfile # Docker配置
└── docker-compose.yml # 容器编排
第二步:定义数据模型(5分钟)
diff
你:"创建数据库模型:
- User表(id, email, password, name, createdAt)
- Todo表(id, title, description, completed, userId, createdAt)
- 建立关联关系"
Claude Code:
✓ 编写Prisma schema
✓ 生成数据库迁移
✓ 创建类型定义
✓ 生成Prisma Client
生成的schema.prisma:
prisma
model User {
id String @id @default(cuid())
email String @unique
password String
name String?
todos Todo[]
createdAt DateTime @default(now())
}
model Todo {
id String @id @default(cuid())
title String
description String?
completed Boolean @default(false)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
第三步:实现认证系统(8分钟)
diff
你:"实现JWT认证系统:
- 用户注册(密码bcrypt加密)
- 用户登录(返回JWT token)
- 认证中间件(验证token)
- 错误处理"
Claude Code:
✓ 创建auth controller
✓ 实现密码加密
✓ 生成JWT token
✓ 创建认证中间件
✓ 添加错误处理
✓ 写单元测试
关键代码片段:
typescript
// src/middleware/auth.ts
export const authenticate = async (req: Request, res: Response, next: NextFunction) => {
try {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
const decoded = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload;
const user = await prisma.user.findUnique({ where: { id: decoded.userId } });
if (!user) {
return res.status(401).json({ error: 'Invalid token' });
}
req.user = user;
next();
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
};
第四步:实现Todo CRUD接口(7分钟)
diff
你:"实现Todo的CRUD接口:
- GET /api/todos(获取用户的所有todos)
- POST /api/todos(创建todo)
- PUT /api/todos/:id(更新todo)
- DELETE /api/todos/:id(删除todo)
- 添加Zod验证
- 只能操作自己的todos"
Claude Code:
✓ 创建routes和controllers
✓ 实现所有CRUD操作
✓ 添加Zod验证schemas
✓ 实现权限检查
✓ 添加错误处理
✓ 写集成测试
API示例:
typescript
// src/routes/todos.ts
router.post('/', authenticate, async (req, res) => {
try {
const data = createTodoSchema.parse(req.body);
const todo = await prisma.todo.create({
data: {
...data,
userId: req.user!.id,
},
});
res.status(201).json(todo);
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({ errors: error.errors });
}
res.status(500).json({ error: 'Internal server error' });
}
});
第五步:添加API文档和部署(5分钟)
arduino
你:"添加Swagger API文档,创建Docker配置用于部署"
Claude Code:
✓ 安装swagger-jsdoc和swagger-ui-express
✓ 为所有接口添加文档注释
✓ 配置Swagger UI
✓ 创建Dockerfile
✓ 创建docker-compose.yml(包含PostgreSQL)
✓ 添加部署README
docker-compose.yml:
yaml
version: '3.8'
services:
api:
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://postgres:password@db:5432/todos
JWT_SECRET: your-secret-key
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: password
POSTGRES_DB: todos
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
第六步:测试和验证
arduino
你:"运行所有测试,启动服务验证功能"
Claude Code:
✓ 运行单元测试(20个通过)
✓ 运行集成测试(15个通过)
✓ 启动开发服务器
✓ 测试所有API端点
✓ 验证认证流程
测试结果:
bash
Test Suites: 5 passed, 5 total
Tests: 35 passed, 35 total
Snapshots: 0 total
Time: 3.521 s
✅ 所有功能正常
✅ API文档可访问:http://localhost:3000/api-docs
✅ 准备部署
项目成果
30分钟内完成:
- ✅ 完整的用户认证系统
- ✅ CRUD API接口
- ✅ 数据库集成
- ✅ 输入验证和错误处理
- ✅ API文档
- ✅ Docker部署配置
- ✅ 35个通过的测试用例
传统开发时间:2-3天
项目2:实时聊天应用前端(45分钟完成)
项目目标
使用Next.js创建一个现代化的聊天应用前端:
- 用户界面(登录、聊天室)
- 实时消息(WebSocket)
- 响应式设计
- TypeScript类型安全
- 状态管理(Zustand)
- 部署到Vercel
第一步:创建Next.js项目(5分钟)
diff
你:"创建Next.js 14项目,配置:
- TypeScript
- Tailwind CSS
- App Router
- Zustand状态管理
- Socket.io客户端
- 项目名:chat-frontend"
Claude Code:
✓ 初始化Next.js项目
✓ 配置Tailwind CSS
✓ 安装依赖
✓ 配置TypeScript strict模式
✓ 创建基础布局
第二步:设计组件结构(10分钟)
diff
你:"创建组件结构:
- LoginForm(登录表单)
- ChatRoom(聊天主界面)
- MessageList(消息列表)
- MessageInput(消息输入框)
- UserList(在线用户列表)
使用Tailwind CSS实现现代化设计"
Claude Code:
✓ 创建所有组件
✓ 实现响应式布局
✓ 添加TypeScript接口
✓ 应用Tailwind样式
✓ 添加加载和错误状态
关键组件示例:
typescript
// components/ChatRoom.tsx
'use client';
export default function ChatRoom({ username }: { username: string }) {
const { messages, users, sendMessage } = useChatStore();
const [input, setInput] = useState('');
const handleSend = () => {
if (input.trim()) {
sendMessage(input);
setInput('');
}
};
return (
<div className="flex h-screen bg-gray-100">
{/* 侧边栏 - 在线用户 */}
<aside className="w-64 bg-white border-r">
<div className="p-4 border-b">
<h2 className="font-semibold text-lg">在线用户</h2>
</div>
<ul className="p-2">
{users.map(user => (
<li key={user.id} className="p-2 hover:bg-gray-50 rounded">
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-green-500 rounded-full" />
<span>{user.name}</span>
</div>
</li>
))}
</ul>
</aside>
{/* 主聊天区域 */}
<main className="flex-1 flex flex-col">
<header className="bg-white border-b p-4">
<h1 className="font-semibold text-xl">聊天室</h1>
</header>
<MessageList messages={messages} />
<MessageInput
value={input}
onChange={setInput}
onSend={handleSend}
/>
</main>
</div>
);
}
第三步:实现WebSocket连接(10分钟)
diff
你:"实现Socket.io客户端连接:
- 连接到服务器
- 发送和接收消息
- 用户加入/离开通知
- 自动重连
- 错误处理"
Claude Code:
✓ 创建socket hook
✓ 实现消息发送/接收
✓ 处理连接状态
✓ 添加重连逻辑
✓ 实现事件监听
Socket Hook:
typescript
// hooks/useSocket.ts
export function useSocket(username: string) {
const [socket, setSocket] = useState<Socket | null>(null);
const [connected, setConnected] = useState(false);
useEffect(() => {
const newSocket = io(process.env.NEXT_PUBLIC_API_URL!, {
query: { username },
reconnection: true,
reconnectionDelay: 1000,
});
newSocket.on('connect', () => {
setConnected(true);
console.log('Connected to server');
});
newSocket.on('disconnect', () => {
setConnected(false);
console.log('Disconnected from server');
});
newSocket.on('message', (message: Message) => {
useChatStore.getState().addMessage(message);
});
newSocket.on('userJoined', (user: User) => {
useChatStore.getState().addUser(user);
});
newSocket.on('userLeft', (userId: string) => {
useChatStore.getState().removeUser(userId);
});
setSocket(newSocket);
return () => {
newSocket.close();
};
}, [username]);
return { socket, connected };
}
第四步:状态管理(10分钟)
diff
你:"使用Zustand创建状态管理:
- 消息列表
- 在线用户列表
- 当前用户信息
- 发送消息方法"
Claude Code:
✓ 创建Zustand store
✓ 实现状态更新方法
✓ 添加TypeScript类型
✓ 实现消息排序和过滤
Store实现:
typescript
// store/chatStore.ts
interface ChatState {
messages: Message[];
users: User[];
currentUser: User | null;
addMessage: (message: Message) => void;
addUser: (user: User) => void;
removeUser: (userId: string) => void;
setCurrentUser: (user: User) => void;
}
export const useChatStore = create<ChatState>((set) => ({
messages: [],
users: [],
currentUser: null,
addMessage: (message) =>
set((state) => ({
messages: [...state.messages, message].slice(-100), // 只保留最近100条
})),
addUser: (user) =>
set((state) => ({
users: [...state.users, user],
})),
removeUser: (userId) =>
set((state) => ({
users: state.users.filter((u) => u.id !== userId),
})),
setCurrentUser: (user) => set({ currentUser: user }),
}));
第五步:优化和部署(10分钟)
diff
你:"优化性能并配置Vercel部署:
- 添加消息虚拟滚动
- 图片懒加载
- 代码分割
- 配置环境变量
- 创建Vercel配置"
Claude Code:
✓ 使用react-window实现虚拟列表
✓ 添加Next.js Image优化
✓ 配置动态导入
✓ 创建vercel.json
✓ 添加环境变量配置
✓ 优化构建大小
部署配置:
json
// vercel.json
{
"env": {
"NEXT_PUBLIC_API_URL": "@chat-api-url"
},
"build": {
"env": {
"NEXT_PUBLIC_API_URL": "@chat-api-url"
}
}
}
项目成果
45分钟内完成:
- ✅ 完整的聊天界面
- ✅ 实时消息功能
- ✅ 响应式设计(支持移动端)
- ✅ 状态管理
- ✅ 性能优化
- ✅ 准备部署到Vercel
传统开发时间:3-5天
项目3:全栈博客系统(60分钟完成)
项目目标
从零搭建一个完整的博客系统:
- 前端(Next.js)
- 后端API(Node.js)
- 数据库(PostgreSQL)
- Markdown编辑器
- 图片上传
- SEO优化
- 部署完整系统
第一步:项目架构设计(5分钟)
diff
你:"创建全栈博客项目架构:
- monorepo结构(使用pnpm workspace)
- packages/web(Next.js前端)
- packages/api(Express后端)
- packages/shared(共享类型)
- 配置TypeScript paths"
Claude Code:
✓ 初始化monorepo
✓ 创建workspace配置
✓ 设置packages结构
✓ 配置TypeScript paths
✓ 创建共享类型包
项目结构:
perl
blog-system/
├── packages/
│ ├── web/ # Next.js前端
│ ├── api/ # Express后端
│ └── shared/ # 共享类型和工具
├── pnpm-workspace.yaml
└── package.json
第二步:后端API开发(20分钟)
diff
你:"实现博客后端API:
- 数据模型(User, Post, Comment, Tag)
- 认证系统
- 文章CRUD
- 评论系统
- 标签管理
- 图片上传(使用S3或本地存储)
- 分页和搜索"
Claude Code:
✓ 创建Prisma schema(4个模型)
✓ 实现JWT认证
✓ 实现所有CRUD接口
✓ 添加分页和排序
✓ 实现全文搜索
✓ 集成文件上传
✓ 添加API测试
核心Schema:
prisma
model User {
id String @id @default(cuid())
email String @unique
password String
name String
avatar String?
posts Post[]
comments Comment[]
createdAt DateTime @default(now())
}
model Post {
id String @id @default(cuid())
title String
slug String @unique
content String @db.Text
excerpt String?
coverImage String?
published Boolean @default(false)
authorId String
author User @relation(fields: [authorId], references: [id])
tags Tag[]
comments Comment[]
viewCount Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Comment {
id String @id @default(cuid())
content String
postId String
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
authorId String
author User @relation(fields: [authorId], references: [id])
createdAt DateTime @default(now())
}
model Tag {
id String @id @default(cuid())
name String @unique
slug String @unique
posts Post[]
}
核心API实现:
typescript
// 获取文章列表(带分页、搜索、标签过滤)
router.get('/posts', async (req, res) => {
const { page = 1, limit = 10, search, tag } = req.query;
const where = {
published: true,
...(search && {
OR: [
{ title: { contains: search, mode: 'insensitive' } },
{ content: { contains: search, mode: 'insensitive' } },
],
}),
...(tag && {
tags: { some: { slug: tag } },
}),
};
const [posts, total] = await Promise.all([
prisma.post.findMany({
where,
include: {
author: { select: { id: true, name: true, avatar: true } },
tags: true,
_count: { select: { comments: true } },
},
skip: (page - 1) * limit,
take: limit,
orderBy: { createdAt: 'desc' },
}),
prisma.post.count({ where }),
]);
res.json({
posts,
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit),
},
});
});
第三步:前端页面开发(25分钟)
diff
你:"创建博客前端页面:
- 首页(文章列表)
- 文章详情页
- 文章编辑器(Markdown)
- 用户个人中心
- 标签页面
- 搜索功能
- 响应式设计
- SEO优化(元标签、sitemap)"
Claude Code:
✓ 创建所有页面组件
✓ 集成Markdown编辑器
✓ 实现文章列表和详情
✓ 添加搜索和过滤
✓ 实现响应式布局
✓ 配置SEO元数据
✓ 生成sitemap
首页实现:
typescript
// app/page.tsx
export default async function HomePage({
searchParams,
}: {
searchParams: { page?: string; tag?: string; search?: string };
}) {
const page = Number(searchParams.page) || 1;
const { posts, pagination } = await fetchPosts({
page,
tag: searchParams.tag,
search: searchParams.search,
});
return (
<div className="container mx-auto px-4 py-8">
<header className="mb-12">
<h1 className="text-4xl font-bold mb-4">技术博客</h1>
<SearchBar defaultValue={searchParams.search} />
</header>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{posts.map((post) => (
<PostCard key={post.id} post={post} />
))}
</div>
<Pagination pagination={pagination} />
</div>
);
}
// 生成静态元数据
export function generateMetadata(): Metadata {
return {
title: '首页 - 技术博客',
description: '分享技术文章和开发经验',
openGraph: {
title: '技术博客',
description: '分享技术文章和开发经验',
type: 'website',
},
};
}
文章详情页:
typescript
// app/posts/[slug]/page.tsx
export default async function PostPage({
params,
}: {
params: { slug: string };
}) {
const post = await fetchPost(params.slug);
if (!post) {
notFound();
}
// 增加浏览量
await incrementViewCount(post.id);
return (
<article className="container mx-auto px-4 py-8 max-w-4xl">
<header className="mb-8">
{post.coverImage && (
<Image
src={post.coverImage}
alt={post.title}
width={1200}
height={600}
className="rounded-lg mb-6"
/>
)}
<h1 className="text-4xl font-bold mb-4">{post.title}</h1>
<div className="flex items-center gap-4 text-gray-600">
<AuthorInfo author={post.author} />
<time>{formatDate(post.createdAt)}</time>
<span>{post.viewCount} 次阅读</span>
</div>
<div className="flex gap-2 mt-4">
{post.tags.map((tag) => (
<Link
key={tag.id}
href={`/?tag=${tag.slug}`}
className="px-3 py-1 bg-blue-100 text-blue-700 rounded-full text-sm"
>
{tag.name}
</Link>
))}
</div>
</header>
{/* Markdown内容渲染 */}
<MarkdownContent content={post.content} />
{/* 评论区 */}
<Comments postId={post.id} />
</article>
);
}
// 动态元数据
export async function generateMetadata({
params,
}: {
params: { slug: string };
}): Promise<Metadata> {
const post = await fetchPost(params.slug);
if (!post) {
return {};
}
return {
title: `${post.title} - 技术博客`,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: post.coverImage ? [post.coverImage] : [],
type: 'article',
publishedTime: post.createdAt,
authors: [post.author.name],
},
};
}
Markdown编辑器:
typescript
// components/MarkdownEditor.tsx
'use client';
import { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
export default function MarkdownEditor({
value,
onChange,
}: {
value: string;
onChange: (value: string) => void;
}) {
const [preview, setPreview] = useState(false);
return (
<div className="border rounded-lg overflow-hidden">
<div className="flex border-b bg-gray-50">
<button
onClick={() => setPreview(false)}
className={`px-4 py-2 ${!preview ? 'bg-white border-b-2 border-blue-500' : ''}`}
>
编辑
</button>
<button
onClick={() => setPreview(true)}
className={`px-4 py-2 ${preview ? 'bg-white border-b-2 border-blue-500' : ''}`}
>
预览
</button>
</div>
{preview ? (
<div className="p-4 prose max-w-none">
<ReactMarkdown
components={{
code({ inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '');
return !inline && match ? (
<SyntaxHighlighter language={match[1]} {...props}>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
);
},
}}
>
{value}
</ReactMarkdown>
</div>
) : (
<textarea
value={value}
onChange={(e) => onChange(e.target.value)}
className="w-full h-96 p-4 font-mono text-sm resize-none focus:outline-none"
placeholder="使用Markdown格式编写文章..."
/>
)}
</div>
);
}
第四步:功能整合和测试(5分钟)
arduino
你:"整合前后端,添加错误处理,运行完整测试"
Claude Code:
✓ 配置CORS和代理
✓ 实现API错误处理
✓ 添加加载状态
✓ 运行前端测试
✓ 运行后端测试
✓ 端到端测试
第五步:部署配置(5分钟)
diff
你:"创建部署配置:
- 前端部署到Vercel
- 后端部署到Railway
- 数据库使用Supabase PostgreSQL
- 配置环境变量
- 设置CI/CD"
Claude Code:
✓ 创建Vercel配置
✓ 创建Railway配置
✓ 配置数据库连接
✓ 设置GitHub Actions
✓ 创建部署文档
部署架构:
scss
┌─────────────┐
│ Vercel │ Next.js前端
│ (CDN) │
└──────┬──────┘
│ API请求
↓
┌─────────────┐
│ Railway │ Node.js后端
│ (Server) │
└──────┬──────┘
│ 数据查询
↓
┌─────────────┐
│ Supabase │ PostgreSQL
│ (Database) │
└─────────────┘
项目成果
60分钟内完成:
- ✅ 完整的前后端系统
- ✅ 用户认证和授权
- ✅ 文章发布和管理
- ✅ Markdown编辑器
- ✅ 评论系统
- ✅ 标签和搜索
- ✅ SEO优化
- ✅ 响应式设计
- ✅ 生产部署配置
传统开发时间:1-2周
三个项目的关键经验
1. 清晰的需求描述
好的描述:
diff
创建用户认证系统:
- JWT token
- 密码bcrypt加密
- 登录/注册接口
- 认证中间件
- 错误处理
差的描述:
arduino
"帮我做个登录功能"
越具体,AI生成的代码越符合需求。
2. 分步骤推进
不要一次性要求完成整个项目,而是:
- 先搭架子(项目结构)
- 再实现核心功能
- 然后添加辅助功能
- 最后优化和部署
每一步验证通过再继续。
3. 充分利用AI的能力
AI特别擅长:
- 生成样板代码(boilerplate)
- 实现标准功能(CRUD、认证)
- 编写测试用例
- 配置工具(TypeScript、ESLint)
- 创建部署配置
把这些交给AI,你专注于业务逻辑。
4. 保持代码审查
AI生成的代码需要你审查:
- 业务逻辑是否正确
- 安全性是否考虑周全
- 性能是否满足要求
- 代码是否符合团队规范
AI是工具,最终质量由你把关。
5. 善用迭代优化
第一版不完美没关系:
arduino
你:"这个登录逻辑需要添加验证码"
AI:[添加验证码功能]
你:"验证码改用图片验证码"
AI:[实现图片验证码]
你:"添加验证码过期时间"
AI:[添加过期逻辑]
逐步完善比一次性要求完美更高效。
部署检查清单
前端部署(Vercel)
- 配置环境变量
- 设置API_URL指向后端
- 配置自定义域名
- 启用HTTPS
- 配置CDN缓存
- 设置错误页面
后端部署(Railway/Render)
- 配置环境变量
- 设置DATABASE_URL
- 配置JWT_SECRET
- 运行数据库迁移
- 配置CORS白名单
- 设置健康检查端点
- 启用日志收集
数据库(Supabase/PlanetScale)
- 创建生产数据库
- 运行迁移脚本
- 配置备份策略
- 设置连接池
- 启用SSL连接
- 配置访问权限
监控和维护
- 设置错误追踪(Sentry)
- 配置性能监控
- 设置告警通知
- 准备回滚方案
- 配置CI/CD流水线
成本预估
个人项目/MVP
月成本:$0-20
- Vercel Free Tier(前端)
- Railway Free Tier(后端)
- Supabase Free Tier(数据库500MB)
- 适合:个人项目、原型验证
小型生产应用
月成本:$20-100
- Vercel Pro $20(前端)
- Railway Hobby $5-20(后端)
- Supabase Pro $25(数据库8GB)
- 适合:小型SaaS、个人商业项目
中型应用
月成本:$100-500
- Vercel Team $100+(多项目)
- Railway/Render $50-200(扩展资源)
- Supabase Team $100+(更大容量)
- 适合:成长型创业公司
实战技巧总结
1. 使用模板加速
首次创建项目让AI生成,后续项目复用:
arduino
你:"使用之前创建的todo-api作为模板,
创建一个events-api项目"
AI:复用项目结构,修改业务逻辑
2. 并行开发
前后端可以同时进行:
bash
# 同时开发
终端1:开发后端API
终端2:开发前端页面
终端3:运行测试
3. 自动化测试
让AI生成测试用例:
arduino
你:"为所有API接口生成集成测试"
AI:
✓ 创建测试文件
✓ 实现所有测试用例
✓ 添加测试数据
✓ 配置测试环境
4. 文档自动生成
diff
你:"为项目生成README文档,包括:
- 项目介绍
- 安装步骤
- API文档
- 部署指南"
AI:生成完整文档
下一步行动
完成这3个项目后,你已经掌握了:
- ✅ 后端API开发流程
- ✅ 前端应用构建
- ✅ 全栈项目整合
- ✅ 生产部署实践
接下来可以:
- 选择一个项目深度优化(性能、安全性)
- 添加更多功能(支付、通知、分析)
- 开发自己的产品创意
- 学习高级技巧(缓存、队列、微服务)
关键是:动手实践,持续迭代。
不要追求第一次就完美,先做出来,再慢慢优化。Claude Code会陪你完成整个过程。