← 返回资讯
陈默
AI 行业分析师
已审核

AI 结对编程工作流:我和 Claude 配合开发了一个 SaaS 产品

过去 3 个月,我用 AI 结对编程的方式开发了一个完整的 SaaS 产品。从需求分析到上线,AI 参与了 80% 的代码编写。

AI 结对编程工作流:我和 Claude 配合开发了一个 SaaS 产品

AI 结对编程工作流:我和 Claude 配合开发了一个 SaaS 产品

过去 3 个月,我用 AI 结对编程的方式开发了一个完整的 SaaS 产品。从需求分析到上线,AI 参与了 80% 的代码编写。

这篇文章分享我的工作流和实战经验。

产品概述

一个 AI 写作助手 SaaS,功能包括:

技术栈:Next.js + TypeScript + Supabase + Stripe

工作流设计

角色分工

| 角色 | 职责 |

|------|------|

| 我(人类) | 需求分析、架构设计、代码审查、部署 |

| AI(Claude) | 代码实现、测试编写、文档生成、Bug 修复 |

日常流程

CODE
1. 需求分析(我)
   ↓
2. 技术方案(我 + AI 讨论)
   ↓
3. 代码实现(AI 写,我审查)
   ↓
4. 测试(AI 写测试,我验证)
   ↓
5. 部署(我操作)

实战案例

案例 1:用户认证模块

我的输入

CODE
实现用户认证模块,要求:
1. 使用 Supabase Auth
2. 支持邮箱和 Google 登录
3. 登录后跳转到 dashboard
4. 未登录访问受保护页面时重定向到登录页

AI 生成的代码

TYPESCRIPT
// src/lib/supabase.ts
import { createClient } from '@supabase/supabase-js';

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

// src/middleware.ts
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs';
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export async function middleware(req: NextRequest) {
  const res = NextResponse.next();
  const supabase = createMiddlewareClient({ req, res });
  
  const { data: { session } } = await supabase.auth.getSession();
  
  // 受保护路由
  if (req.nextUrl.pathname.startsWith('/dashboard')) {
    if (!session) {
      return NextResponse.redirect(new URL('/login', req.url));
    }
  }
  
  // 已登录用户访问登录页,重定向到 dashboard
  if (req.nextUrl.pathname === '/login' && session) {
    return NextResponse.redirect(new URL('/dashboard', req.url));
  }
  
  return res;
}

export const config = {
  matcher: ['/dashboard/:path*', '/login']
};

我的审查意见

AI 修改后

TYPESCRIPT
// 添加了错误边界和 loading 状态
export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const { data: { subscription } } = supabase.auth.onAuthStateChange(
      (event, session) => {
        setUser(session?.user ?? null);
        setLoading(false);
      }
    );

    return () => subscription.unsubscribe();
  }, []);

  if (loading) {
    return <LoadingSpinner />;
  }

  return (
    <AuthContext.Provider value={{ user, loading }}>
      {children}
    </AuthContext.Provider>
  );
}

案例 2:AI 文章生成

我的输入

CODE
实现 AI 文章生成功能:
1. 用户输入主题和关键词
2. 调用 OpenAI API 生成文章
3. 支持流式输出
4. 生成完成后保存到数据库

AI 生成的代码

TYPESCRIPT
// src/app/api/generate/route.ts
import { NextRequest } from 'next/server';
import OpenAI from 'openai';
import { supabase } from '@/lib/supabase';

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

export async function POST(req: NextRequest) {
  const { topic, keywords, userId } = await req.json();

  // 创建流式响应
  const stream = new ReadableStream({
    async start(controller) {
      const encoder = new TextEncoder();
      
      try {
        const completion = await openai.chat.completions.create({
          model: 'gpt-4',
          messages: [
            {
              role: 'system',
              content: '你是一个专业的文章写作助手。'
            },
            {
              role: 'user',
              content: `请根据以下信息写一篇文章:
                主题:${topic}
                关键词:${keywords.join(', ')}
              `
            }
          ],
          stream: true,
        });

        let fullContent = '';

        for await (const chunk of completion) {
          const content = chunk.choices[0]?.delta?.content || '';
          fullContent += content;
          controller.enqueue(encoder.encode(`data: ${JSON.stringify({ content })}\n\n`));
        }

        // 保存到数据库
        const { data, error } = await supabase
          .from('articles')
          .insert({
            user_id: userId,
            topic,
            keywords,
            content: fullContent,
            status: 'draft'
          })
          .select()
          .single();

        if (error) throw error;

        controller.enqueue(encoder.encode(`data: ${JSON.stringify({ 
          done: true, 
          articleId: data.id 
        })}\n\n`));
        
      } catch (error) {
        controller.enqueue(encoder.encode(`data: ${JSON.stringify({ 
          error: '生成失败' 
        })}\n\n`));
      }

      controller.close();
    }
  });

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
    },
  });
}
TYPESCRIPT
// src/components/ArticleGenerator.tsx
'use client';

import { useState } from 'react';

export function ArticleGenerator() {
  const [topic, setTopic] = useState('');
  const [keywords, setKeywords] = useState('');
  const [content, setContent] = useState('');
  const [generating, setGenerating] = useState(false);

  const handleGenerate = async () => {
    setGenerating(true);
    setContent('');

    const response = await fetch('/api/generate', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        topic,
        keywords: keywords.split(',').map(k => k.trim()),
        userId: 'current-user-id'
      }),
    });

    const reader = response.body?.getReader();
    const decoder = new TextDecoder();

    while (true) {
      const { done, value } = await reader!.read();
      if (done) break;

      const text = decoder.decode(value);
      const lines = text.split('\n').filter(line => line.startsWith('data: '));

      for (const line of lines) {
        const data = JSON.parse(line.slice(6));
        
        if (data.content) {
          setContent(prev => prev + data.content);
        }
        
        if (data.done) {
          setGenerating(false);
        }
        
        if (data.error) {
          alert(data.error);
          setGenerating(false);
        }
      }
    }
  };

  return (
    <div className="space-y-4">
      <input
        value={topic}
        onChange={e => setTopic(e.target.value)}
        placeholder="输入文章主题"
        className="w-full p-2 border rounded"
      />
      
      <input
        value={keywords}
        onChange={e => setKeywords(e.target.value)}
        placeholder="输入关键词,用逗号分隔"
        className="w-full p-2 border rounded"
      />
      
      <button
        onClick={handleGenerate}
        disabled={generating || !topic}
        className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
      >
        {generating ? '生成中...' : '生成文章'}
      </button>
      
      {content && (
        <div className="prose max-w-none">
          {content}
        </div>
      )}
    </div>
  );
}

案例 3:Stripe 支付集成

我的输入

CODE
集成 Stripe 订阅支付:
1. 月付 $19,年付 $190
2. 创建 checkout session
3. 处理 webhook 事件
4. 更新用户订阅状态

AI 生成的代码

TYPESCRIPT
// src/app/api/checkout/route.ts
import Stripe from 'stripe';
import { NextRequest, NextResponse } from 'next/server';
import { supabase } from '@/lib/supabase';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2024-06-20',
});

const PRICES = {
  monthly: 'price_monthly_xxx',
  yearly: 'price_yearly_xxx',
};

export async function POST(req: NextRequest) {
  const { plan, userId } = await req.json();

  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    payment_method_types: ['card'],
    line_items: [
      {
        price: PRICES[plan as keyof typeof PRICES],
        quantity: 1,
      },
    ],
    success_url: `${process.env.NEXT_PUBLIC_URL}/dashboard?success=true`,
    cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing?canceled=true`,
    metadata: { userId },
  });

  return NextResponse.json({ url: session.url });
}

// src/app/api/webhook/route.ts
export async function POST(req: NextRequest) {
  const body = await req.text();
  const sig = req.headers.get('stripe-signature')!;

  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(
      body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET!
    );
  } catch (err) {
    return NextResponse.json({ error: 'Webhook Error' }, { status: 400 });
  }

  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object as Stripe.Checkout.Session;
      await supabase
        .from('subscriptions')
        .insert({
          user_id: session.metadata?.userId,
          stripe_subscription_id: session.subscription as string,
          status: 'active',
        });
      break;
    }

    case 'customer.subscription.deleted': {
      const subscription = event.data.object as Stripe.Subscription;
      await supabase
        .from('subscriptions')
        .update({ status: 'canceled' })
        .eq('stripe_subscription_id', subscription.id);
      break;
    }
  }

  return NextResponse.json({ received: true });
}

效率数据

3 个月的开发数据:

| 指标 | 数值 |

|------|------|

| 总代码行数 | 28,500 行 |

| AI 生成比例 | 82% |

| 人工修改比例 | 18% |

| 开发周期 | 12 周 |

| 单人开发 | 是 |

如果没有 AI,估计需要 6-8 个月。

经验总结

有效的做法

1. 明确需求:给 AI 清晰的指令

2. 分步实现:大功能拆成小任务

3. 及时审查:每段代码都要审查

4. 持续测试:边写边测

需要避免的

1. 盲目信任:AI 生成的代码不一定正确

2. 一次太多:一次让 AI 写太多容易出错

3. 忽略边界:AI 经常忽略边界条件

4. 跳过测试:一定要写测试

总结

AI 结对编程可以大幅提升开发效率,但需要正确的工作流。

关键原则

1. 人类负责决策和审查

2. AI 负责实现和执行

3. 保持紧密的反馈循环

4. 不要跳过任何审查步骤


开发时间:2026年4月-7月

产品状态:已上线

用户数:500+

#AI编程 #结对编程 #SaaS #开发效率

233
5836 阅读
2 评论
分享
链接已复制
编辑说明

本文由 MakeSense 编辑团队撰写并审核。文中引用的数据和观点均经过交叉验证,如有疏漏欢迎在评论区指正。最后更新:2026年07月10日 17:48

陈默

AI 行业分析师

前某大厂 AI 实验室研究员,关注大模型技术演进和商业化落地。写过 200+ 篇行业分析,擅长从产品视角拆解技术趋势。

读者评论 2

数据分析师 1周前
数据引用很扎实,建议补充一下近三个月的最新数据。
回复 点赞 (9)
产品经理阿杰 2周前
从产品角度看,这个方向确实有机会,但商业化路径还需要验证。
回复 点赞 (15)