Next.js 16 + Supabase + Vercel:SmartChat 全栈 AI 应用架构实战
前言
全栈 AI 应用怎么选技术栈?这个问题没有标准答案,但 SmartChat 的选择——Next.js 16 + Supabase + Vercel——是一套经过验证的高效组合。本文从架构角度拆解这套技术栈的设计思路。
🔗 项目地址:smartchat.nofx.asia/
![]()
一、为什么是 Next.js 16?
SmartChat 使用 Next.js 16 的 App Router,充分利用了以下特性:
Server Components: 仪表盘页面使用 Server Components 直接在服务端查询数据库,减少客户端 JS 体积。
API Routes(Serverless): 所有后端逻辑通过 API Routes 实现,无需维护独立的后端服务。
src/app/api/
├── chat/ # 聊天接口(SSE 流式)
├── bots/ # 机器人 CRUD
├── upload/ # 文档上传与向量化
└── conversations/ # 对话管理
Turbopack: 开发环境使用 Turbopack,热更新速度显著提升。
关键优势:前后端同仓库、同语言(TypeScript)、同部署,极大降低了开发和运维复杂度。
二、Supabase:不只是数据库
SmartChat 用 Supabase 承担了多个角色:
2.1 PostgreSQL 数据库 + pgvector
-- 业务数据和向量数据在同一个库
CREATE TABLE document_chunks (
id uuid PRIMARY KEY,
bot_id uuid REFERENCES bots(id) ON DELETE CASCADE,
content text,
embedding vector(512), -- pgvector 向量列
metadata jsonb
);
-- IVFFlat 索引加速向量检索
CREATE INDEX ON document_chunks
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
2.2 用户认证(Supabase Auth)
内置邮箱/密码、OAuth 登录,无需自建认证系统。
2.3 行级安全(RLS)
-- 用户只能访问自己的机器人
CREATE POLICY "Users can only access own bots" ON bots
FOR ALL USING (auth.uid() = user_id);
-- 匿名访客可以查看公开的机器人配置
CREATE POLICY "Public bot access" ON bots
FOR SELECT USING (is_public = true);
RLS 确保了多租户数据隔离,同时通过 Service Role 客户端允许匿名访客与机器人对话。
2.4 文件存储
文档上传使用 Supabase Storage,统一管理。
![]()
三、可嵌入组件设计
SmartChat 的一大亮点是一行代码嵌入任何网站:
<script src="https://your-domain.com/embed.js" data-bot-id="xxx"></script>
实现原理:
// embed.js 核心逻辑
(function() {
const botId = document.currentScript.getAttribute('data-bot-id');
// 创建 iframe 容器
const iframe = document.createElement('iframe');
iframe.src = `https://your-domain.com/chat/${botId}?embed=true`;
iframe.style.cssText = 'position:fixed;bottom:20px;right:20px;...';
// 创建触发按钮
const button = document.createElement('div');
button.onclick = () => iframe.classList.toggle('visible');
document.body.appendChild(button);
document.body.appendChild(iframe);
})();
通过 iframe 隔离样式和脚本,避免与宿主网站冲突。聊天界面的颜色、头像、欢迎语都可以在后台自定义。
![]()
![]()
四、SSE 流式响应架构
SmartChat 使用 Server-Sent Events 实现实时流式输出:
// API Route: /api/chat
export async function POST(req: Request) {
const { message, botId, conversationId } = await req.json();
// 1. 向量检索相关文档
const relevantDocs = await searchDocuments(message, botId);
// 2. 构建带上下文的 Prompt
const messages = await buildMessages(conversationId, relevantDocs);
// 3. 流式调用 LLM
const stream = await streamChat({ provider, model, messages });
// 4. 返回 SSE 流
return new Response(
new ReadableStream({
async start(controller) {
let fullResponse = '';
for await (const chunk of stream) {
const text = extractText(chunk);
fullResponse += text;
controller.enqueue(`data: ${JSON.stringify({ text })}\n\n`);
}
// 5. 流结束后,附加来源信息
controller.enqueue(`data: ${JSON.stringify({
sources: relevantDocs
})}\n\n`);
controller.close();
// 6. 异步保存完整回复到数据库
await saveMessage(conversationId, fullResponse, relevantDocs);
}
}),
{ headers: { 'Content-Type': 'text/event-stream' } }
);
}
流程:向量检索 → 构建 Prompt → 流式生成 → 实时推送 → 保存记录。
五、Vercel 一键部署
SmartChat 的 Serverless 架构天然适合 Vercel 部署:
- 零服务器管理:API Routes 自动变成 Serverless Functions
- 全球 CDN:静态资源自动分发
- 自动扩缩容:流量高峰自动扩容,空闲时零成本
- 环境变量管理:在 Vercel Dashboard 配置 API Keys 等敏感信息
部署流程:Fork 仓库 → 连接 Vercel → 配置环境变量 → 部署完成。
六、性能优化要点
- React 19 + Turbopack:开发体验和构建速度大幅提升
- Server Components:减少客户端 JS 体积
- 流式渲染:用户无需等待完整回复
- IVFFlat 索引:向量检索毫秒级响应
- 批量写入:文档分块后每 10 条一批插入,避免超时
总结
Next.js + Supabase + Vercel 这套组合的核心优势是简单:一个仓库、一种语言、一键部署。对于中小团队做 AI 应用,这可能是目前投入产出比最高的技术栈选择。SmartChat 是这套架构的一个完整实践案例。
🔗 项目地址:smartchat.nofx.asia/,MIT 开源协议,支持一键部署到 Vercel。