Claude Code实战:手写一个智能博客系统,效率提升5倍

(开篇图:一个程序员对着屏幕大笑,屏幕上显示“Claude Code: 5x faster”字样,背景是凌乱但充满活力的办公桌)

但经过两周的折磨,我终于找到了正确姿势。今天就用一个真实项目——智能博客系统,带你走一遍Claude Code从入门到实战的全流程。这个项目我从头到尾用了Claude Code辅助开发,从设计到部署只花了一个周末,比传统方式快了至少5倍。

先看项目背景

a2db336_0.png” alt=”先看项目背景 – Claude Code实战:手写一个智能博客系统,效率提升5倍”
style=”max-width:100%;height:auto;border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,.08);”
loading=”lazy” width=”800″ height=”500″>

我要做一个支持Markdown、带评论功能、有AI摘要生成的博客系统。技术栈选的是Next.js + Tailwind CSS + Prisma + SQLite。为什么选这个组合?因为Next.js 14的App Router真香,Prisma操作数据库像写诗一样爽。

坑一:让Claude Code理解项目结构

第一个大坑是让AI理解你的项目。直接问“帮我写一个博客系统”绝对翻车,生成的东西要么太简单,要么结构混乱。

正确做法是先给Claude Code一个清晰的结构蓝图:


项目的核心结构应该是:

  • /app 路由页面
  • /components 通用组件
  • /lib 工具函数和数据库操作
  • /prisma 数据库模型
  • /types 类型定义

`

然后让它基于这个结构生成基础代码。我用的prompt是这样的:

`
你是一个有10年经验的Next.js全栈开发者。请帮我创建一个博客系统的项目结构,要求:

  • 使用Next.js 14 App Router
  • 数据库用Prisma + SQLite
  • 支持Markdown文章发布
  • 有评论功能
  • 能自动生成AI摘要
  • 先只生成项目结构和配置文件,不要写具体业务逻辑。
    `

    Claude Code立刻给出了完整的项目骨架和prisma schema。这里有个小技巧:分阶段提问,不要一次性要求太多

    核心功能实现:文章CRUD

    先看数据库模型。Prisma schema这部分我让Claude Code根据需求自动生成:

    `prisma
    // prisma/schema.prisma
    generator client {
    provider = "prisma-client-js"
    }

    datasource db {
    provider = "sqlite"
    url = env("DATABASE_URL")
    }

    model Post {
    id String @id @default(cuid())
    title String
    slug String @unique
    content String // Markdown内容
    excerpt String? // AI生成的摘要
    tags String? // 逗号分隔
    published Boolean @default(false)
    createdAt DateTime @default(now())
    updatedAt DateTime @updatedAt
    comments Comment[]
    }

    model Comment {
    id String @id @default(cuid())
    postId String
    author String
    content String
    createdAt DateTime @default(now())
    post Post @relation(fields: [postId], references: [id])
    }
    `

    这个设计其实踩了一个坑:excerpt字段最开始没加,后来发现AI摘要没地方存,被迫加字段。所以建议一开始就规划好所有可能用到的字段。

    接下来是核心的CRUD操作。Claude Code生成的代码,我改了两个地方:

  • 错误处理太简单:生成的代码只在控制台console.error,我改成了返回详细错误信息
  • 类型安全不到位:有些地方用了any,我手动补了类型
  • 来看看文章创建API的最终版本:

    `typescript
    // app/api/posts/route.ts
    import { NextRequest, NextResponse } from 'next/server'
    import prisma from '@/lib/prisma'
    import { PostSchema } from '@/types/post'
    import { generateExcerpt } from '@/lib/ai'

    // 辅助函数:生成唯一slug
    function generateSlug(title: string): string {
    const base = title
    .toLowerCase()
    .replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-')
    .replace(/^-|-$/g, '')

    const timestamp = Date.now().toString(36)
    return
    ${base}-${timestamp}
    }

    // 创建文章
    export async function POST(request: NextRequest) {
    try {
    const body = await request.json()

    // 验证输入
    const validation = PostSchema.safeParse(body)
    if (!validation.success) {
    return NextResponse.json(
    { error: '输入数据验证失败', details: validation.error.issues },
    { status: 400 }
    )
    }

    const { title, content, tags } = validation.data

    // 生成slug(这里踩过坑:slug必须唯一)
    let slug = generateSlug(title)
    const existing = await prisma.post.findUnique({ where: { slug } })
    if (existing) {
    slug =
    ${slug}-${Math.random().toString(36).slice(2, 8)}
    }

    // 调用Claude API生成摘要(这个设计真的反人类,返回格式不统一)
    let excerpt = ''
    try {
    excerpt = await generateExcerpt(content)
    } catch (error) {
    console.error('AI摘要生成失败,使用默认值:', error)
    excerpt = content.slice(0, 150) + '...'
    }

    const post = await prisma.post.create({
    data: { title, slug, content, excerpt, tags, published: false }
    })

    return NextResponse.json(post, { status: 201 })
    } catch (error) {
    console.error('创建文章失败:', error)
    return NextResponse.json(
    { error: '服务器内部错误' },
    { status: 500 }
    )
    }
    }
    `

    为什么要这么写?因为Claude Code生成的基础代码只能覆盖80%的场景,剩下的20%需要你根据实际业务逻辑调整。比如上面这段代码,我加了三层防护:

    • 输入验证(防止脏数据)
    • slug唯一性处理(避免冲突)
    • AI摘要降级策略(就算生成失败也不影响发布)

    (中间插图:一张代码对比图,左边是Claude Code生成的原始代码,右边是优化后的最终版本,关键改动用红框标出)

    另一个坑:AI摘要生成器

    这是最让我头大的部分。官方文档说得很简单:“调用Claude API,传入content,返回摘要”。但实际做的时候,你会发现:

  • API返回格式不稳定:有时候返回纯文本,有时候返回JSON
  • token限制:文章太长时直接报错
  • 并发控制:批量生成时API会限流
  • 来看看我最终是怎么处理的:

    `typescript
    // lib/ai.ts
    import Anthropic from '@anthropic-ai/sdk'

    const anthropic = new Anthropic({
    apiKey: process.env.ANTHROPIC_API_KEY,
    })

    // 核心:分段处理长文本
    function splitContent(text: string, maxLength: number = 8000): string[] {
    const chunks: string[] = []
    let current = ''

    for (const paragraph of text.split('\n\n')) {
    if ((current + paragraph).length > maxLength) {
    chunks.push(current.trim())
    current = paragraph
    } else {
    current += '\n\n' + paragraph
    }
    }

    if (current.trim()) {
    chunks.push(current.trim())
    }

    return chunks
    }

    export async function generateExcerpt(content: string): Promise {
    try {
    // 如果内容太长,只保留前8000字符
    const truncatedContent = content.length > 8000
    ? content.slice(0, 8000) + '...'
    : content

    const response = await anthropic.messages.create({
    model: "claude-3-5-sonnet-20241022",
    max_tokens: 200,
    system: "你是一个文字摘要生成器。请用中文为以下文章生成一段50字以内的摘要,直接输出摘要内容,不要任何额外格式。",
    messages: [
    { role: "user", content: truncatedContent }
    ]
    })

    // 处理多种返回格式(这个设计真的反人类)
    const content = response.content[0]
    let excerpt = ''

    if (typeof content === 'string') {
    excerpt = content
    } else if ('text' in content) {
    excerpt = content.text
    } else {
    throw new Error('未知的响应格式')
    }

    // 清理多余的空格和换行
    return excerpt.trim().replace(/\s+/g, ' ')
    } catch (error) {
    // 降级策略:取文章前150字
    console.warn('AI摘要生成失败,使用降级方案:', error)
    const fallback = content.replace(/[#*
    ]/g, ”).slice(0, 150)
    return fallback + (content.length > 150 ? ‘…’ : ”)
    }
    }

    这里有两个关键优化:

    • 分段策略:长文章自动截断,避免超token
    • 降级方案:AI挂了也不影响主流程

    还有个技巧:自动补全和重构

    Claude Code最强的地方不是写新代码,而是重构和补全。比如我写了一个评论组件,写到一半不知道该怎么处理表单状态,直接选中代码让Claude Code补全:

    `
    请基于现有代码,帮我补全评论表单的提交逻辑,包括:

  • 表单验证(名字不能为空,内容至少10个字)
  • 防重复提交(loading状态)
  • 提交成功后清空表单并刷新评论列表
  • `

    它生成的代码虽然有些小问题(比如忘记处理错误状态),但整体框架是对的。我只需要改三行就搞定了,比自己从头写快得多。

    性能优化:从3.2秒到0.8秒

    博客系统搭好后,发现首页加载要3.2秒,这谁受得了?Claude Code帮我分析出瓶颈:

  • 数据库查询太多:每次加载页面都查了3次数据库
  • AI摘要调用慢:每个文章都单独调API
  • 图片没优化:文章里的图片都是原图
  • 我们做了三个优化:

    `typescript
    // 优化1:使用Prisma的include和select精确查询
    const posts = await prisma.post.findMany({
    where: { published: true },
    select: {
    id: true,
    title: true,
    slug: true,
    excerpt: true,
    tags: true,
    createdAt: true,
    _count: { select: { comments: true } }
    },
    orderBy: { createdAt: 'desc' },
    take: 20
    })

    // 优化2:批量生成摘要(不做了,改成懒加载)
    // 只在查看文章详情时才生成或缓存摘要

    // 优化3:图片添加懒加载和WebP支持
    // 使用next/image组件自动优化

    优化后首页加载时间从3.2秒降到了0.8秒,提升了4倍。Claude Code在这个过程中帮了大忙:它自动检测出N+1查询问题,这在传统开发中很容易被忽略。

    部署踩坑记

    部署到Vercel时又碰到几个坑:

  • 环境变量:漏了ANTHROPIC_API_KEY,AI摘要功能全挂
  • 数据库迁移:SQLite在生产环境用不了,必须切换到PostgreSQL
  • 定时任务:用Vercel的Cron Jobs实现每日自动备份
  • Claude Code帮我生成了完整的迁移脚本和CI/CD配置,省了我不少时间。

    (总结前插图:一张流程图,展示从开发到部署的全流程,每个阶段都有Claude Code的介入点,用不同颜色标注)

    总结一下,你可以立刻用的三个点

  • 分阶段提问:不要一次性让Claude Code生成全部代码,先搭骨架再填肉
  • 永远做降级处理:AI生成的内容要准备好Plan B,比如摘要失败就用截取
  • 把Claude Code当高级补全工具:不是让它写全部代码,而是用它补全、重构、查错
  • 这个博客系统的完整代码我放在GitHub上了,链接在评论区。经过这一轮实战,我最大的感受是:Claude Code不是取代程序员,而是把你的效率从“手动挡”升级到“自动挡”。但前提是你要学会怎么开这台车,不然照样翻沟里。

    下次我会分享如何用Claude Code做单元测试和API文档自动化,关注不迷路。

    滚动至顶部