
Vibe Coding 不是“闭眼让 AI 写”,而是把自然语言当成新 IDE:你描述意图,AI 生成骨架,你负责验证、约束与部署。专业全栈开发者的优势不在敲键盘,而在定义边界、拆解任务、审查代码。下面用 Next.js + TypeScript + Prisma + SQLite 跑通一个任务管理应用。
先给 AI 明确技术栈与验收标准:“Next.js 14 App Router、Prisma、SQLite、Zod 校验、REST API”。生成 prisma/schema.prisma:
model Task {
id String @id @default(cuid())
title String
done Boolean @default(false)
createdAt DateTime @default(now())
}执行 npx prisma migrate dev --name init,数据库即就绪。
app/api/tasks/route.ts 需要输入校验与错误处理:
import { NextResponse } from "next/server";
import { z } from "zod";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const TaskInput = z.object({ title: z.string().min(1).max(100) });
export async function GET() {
const tasks = await prisma.task.findMany({ orderBy: { createdAt: "desc" } });
return NextResponse.json(tasks);
}
export async function POST(req: Request) {
const parsed = TaskInput.safeParse(await req.json());
if (!parsed.success) {
return NextResponse.json({ error: "Invalid title" }, { status: 400 });
}
const task = await prisma.task.create({ data: { title: parsed.data.title } });
return NextResponse.json(task, { status: 201 });
}app/page.tsx 用客户端组件调用 API:
"use client";
import { useEffect, useState } from "react";
type Task = { id: string; title: string; done: boolean };
export default function Home() {
const [tasks, setTasks] = useState<Task[]>([]);
const [title, setTitle] = useState("");
async function load() {
setTasks(await (await fetch("/api/tasks")).json());
}
async function add() {
if (!title.trim()) return;
await fetch("/api/tasks", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title }),
});
setTitle("");
load();
}
useEffect(() => { load(); }, []);
return (
<main className="p-8 max-w-md mx-auto">
<h1 className="text-2xl font-bold mb-4">Vibe Tasks</h1>
<div className="flex gap-2">
<input value={title} onChange={(e) => setTitle(e.target.value)}
className="border p-2 flex-1" placeholder="新任务" />
<button onClick={add} className="bg-black text-white px-4">添加</button>
</div>
<ul className="mt-4 space-y-2">
{tasks.map((t) => <li key={t.id} className="border p-2">{t.title}</li>)}
</ul>
</main>
);
}Vibe Coding 最大的风险是“看起来能跑”。必须补自动化测试。tests/task.test.ts:
import { describe, it, expect } from "vitest";
import { z } from "zod";
const TaskInput = z.object({ title: z.string().min(1).max(100) });
describe("TaskInput", () => {
it("拒绝空标题", () => {
expect(TaskInput.safeParse({ title: "" }).success).toBe(false);
});
it("接受合法标题", () => {
expect(TaskInput.safeParse({ title: "写代码" }).success).toBe(true);
});
});GitHub Actions 每次 push 执行类型检查、lint 与测试:
name: ci
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npx prisma generate
- run: npm run lint && npm run typecheck && npm testtsc --noEmit、eslint、vitest 是底线。部署时用 Vercel,设置 DATABASE_URL 与 OPENAI_API_KEY,推送即上线。Vibe Coding 是杠杆,不是替代。把 AI 当实习生,把工程纪律当导师,全栈交付速度与质量才能同时提升。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。