使用 Next.js 16、Clerk 和 Supabase 构建全栈 AI SaaS 应用(2026)
逐步指南:构建一个包含身份验证、用量限制、订阅计费和 AI 功能的生产级 AI SaaS 应用
使用 Next.js 16、Clerk 和 Supabase 构建全栈 AI SaaS 应用(2026)
逐步指南:构建一个包含身份验证、用量限制、订阅计费和 AI 功能的生产级 AI SaaS 应用
完整教程,教你使用 Next.js 16、Clerk 进行身份验证、Supabase 作为数据库、OpenAI 提供 AI 功能,构建全栈 AI SaaS 应用。涵盖用户管理、用量计量、Stripe 计费以及部署到生产环境。
使用 Next.js 16、Clerk 和 Supabase 构建全栈 AI SaaS 应用(2026)
本教程将从零开始构建一个完整的 AI 写作工具 SaaS。最终你将拥有一个可部署的应用,包含身份验证、用量限制、付费计划和 AI 功能。
架构概览
Next.js 16 (App Router)
├── 身份验证:Clerk (SSO、魔法链接、组织管理)
├── 数据库:Supabase (Postgres + pgvector)
├── AI:OpenAI API (GPT-4o)
├── 计费:Stripe (订阅)
└── 部署:Vercel
1. 项目设置
bash
npx create-next-app@latest ai-saas --typescript --tailwind --app
cd ai-saas
bun add @clerk/nextjs @supabase/supabase-js openai stripe @stripe/stripe-js ai @ai-sdk/openai
2. 使用 Clerk 进行身份验证
typescript
// src/middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';const isProtectedRoute = createRouteMatcher([
'/dashboard(.*)',
'/api/ai(.*)',
'/api/usage(.*)',
]);
export default clerkMiddleware((auth, req) => {
if (isProtectedRoute(req)) auth().protect();
});
export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};
typescript
// src/app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
3. Supabase 数据库模式
sql
-- 用户表(从 Clerk 同步)
CREATE TABLE users (
id TEXT PRIMARY KEY, -- Clerk 用户 ID
email TEXT NOT NULL,
name TEXT,
plan TEXT DEFAULT 'free' CHECK (plan IN ('free', 'starter', 'pro')),
created_at TIMESTAMPTZ DEFAULT NOW()
);-- 用量跟踪
CREATE TABLE usage_logs (
id BIGSERIAL PRIMARY KEY,
user_id TEXT REFERENCES users(id),
action TEXT NOT NULL, -- 'generate', 'improve', 'translate'
tokens_used INTEGER DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 月度用量视图
CREATE VIEW monthly_usage AS
SELECT
user_id,
DATE_TRUNC('month', created_at) AS month,
COUNT(*) AS request_count,
SUM(tokens_used) AS total_tokens
FROM usage_logs
GROUP BY user_id, DATE_TRUNC('month', created_at);
-- 计划限制
CREATE TABLE plan_limits (
plan TEXT PRIMARY KEY,
monthly_requests INTEGER,
monthly_tokens INTEGER
);
INSERT INTO plan_limits VALUES
('free', 20, 50000),
('starter', 200, 500000),
('pro', 2000, 5000000);
4. 用量计量
typescript
// src/lib/usage.ts
import { createClient } from '@/lib/supabase/server';
import { auth } from '@clerk/nextjs/server';export async function checkUsageLimit(action: string): Promise {
const { userId } = await auth();
if (!userId) return false;
const supabase = createClient();
// 获取用户的计划和当前月度用量
const { data } = await supabase
.from('users')
.select(`
plan,
plan_limits!users_plan_fkey(monthly_requests)
`)
.eq('id', userId)
.single();
const monthStart = new Date();
monthStart.setDate(1);
monthStart.setHours(0, 0, 0, 0);
const { count } = await supabase
.from('usage_logs')
.select('*', { count: 'exact', head: true })
.eq('user_id', userId)
.gte('created_at', monthStart.toISOString());
const limit = data?.plan_limits?.monthly_requests ?? 20;
return (count ?? 0) < limit;
}
export async function logUsage(action: string, tokensUsed: number) {
const { userId } = await auth();
if (!userId) return;
const supabase = createClient();
await supabase.from('usage_logs').insert({
user_id: userId,
action,
tokens_used: tokensUsed,
});
}
5. AI 功能
typescript
// src/app/api/ai/generate/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
import { auth } from '@clerk/nextjs/server';
import { checkUsageLimit, logUsage } from '@/lib/usage';export async function POST(req: Request) {
const { userId } = await auth();
if (!userId) {
return new Response('Unauthorized', { status: 401 });
}
// 检查用量限制
const canProceed = await checkUsageLimit('generate');
if (!canProceed) {
return new Response(
JSON.stringify({ error: 'Monthly limit reached. Please upgrade your plan.' }),
{ status: 429, headers: { 'Content-Type': 'application/json' } }
);
}
const { prompt, type } = await req.json();
const systemPrompts: Record = {
blog: 'You are an expert blog writer. Create engaging, SEO-optimized content.',
email: 'You are a professional email copywriter. Write clear, effective emails.',
social: 'You are a social media expert. Create engaging posts optimized for each platform.',
};
let tokensUsed = 0;
const result = streamText({
model: openai('gpt-4o'),
system: systemPrompts[type] ?? systemPrompts.blog,
prompt,
onFinish: async ({ usage }) => {
tokensUsed = usage.totalTokens;
await logUsage('generate', tokensUsed);
},
});
return result.toDataStreamResponse();
}
6. Stripe 计费
typescript
// src/app/api/stripe/create-checkout/route.ts
import Stripe from 'stripe';
import { auth } from '@clerk/nextjs/server';
import { NextResponse } from 'next/server';const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const PLANS = {
starter: process.env.STRIPE_STARTER_PRICE_ID!,
pro: process.env.STRIPE_PRO_PRICE_ID!,
};
export async function POST(req: Request) {
const { userId, sessionClaims } = await auth();
if (!userId) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
const { plan } = await req.json() as { plan: 'starter' | 'pro' };
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
payment_method_types: ['card'],
line_items: [{ price: PLANS[plan], quantity: 1 }],
success_url: ${process.env.NEXT_PUBLIC_APP_URL}/dashboard?upgraded=true,
cancel_url: ${process.env.NEXT_PUBLIC_APP_URL}/pricing,
customer_email: sessionClaims?.email as string,
metadata: { userId, plan },
});
return NextResponse.json({ url: session.url });
}
typescript
// src/app/api/stripe/webhook/route.ts
import Stripe from 'stripe';
import { createAdminClient } from '@/lib/supabase/admin';const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: Request) {
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 {
return new Response('Webhook signature verification failed', { status: 400 });
}
const supabase = createAdminClient();
if (event.type === 'checkout.session.completed') {
const session = event.data.object as Stripe.CheckoutSession;
const { userId, plan } = session.metadata as { userId: string; plan: string };
// 更新数据库中的用户计划
await supabase.from('users').upsert({ id: userId, plan });
}
if (event.type === 'customer.subscription.deleted') {
// 取消订阅后降级为免费计划
const subscription = event.data.object as Stripe.Subscription;
const userId = subscription.metadata.userId;
await supabase.from('users').update({ plan: 'free' }).eq('id', userId);
}
return new Response('OK', { status: 200 });
}
7. 定价页面
typescript
// src/app/pricing/page.tsx
import { auth } from '@clerk/nextjs/server';
import { PricingCards } from '@/components/pricing-cards';export default async function PricingPage() {
const { userId } = await auth();
const plans = [
{
name: 'Free',
price: '$0',
period: 'forever',
features: ['20 AI generations/month', 'Basic templates', 'Email support'],
cta: userId ? 'Current Plan' : 'Get Started',
disabled: true,
},
{
name: 'Starter',
price: '$19',
period: '/month',
features: ['200 AI generations/month', 'All templates', 'Priority support', 'API access'],
cta: 'Upgrade to Starter',
plan: 'starter',
highlighted: true,
},
{
name: 'Pro',
price: '$49',
period: '/month',
features: ['2000 AI generations/month', 'Custom AI personas', 'Team collaboration', 'Analytics'],
cta: 'Upgrade to Pro',
plan: 'pro',
},
];
return (
Simple, transparent pricing
);
}
8. 部署清单
bash
所需环境变量:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
SUPABASE_SERVICE_ROLE_KEY=...
OPENAI_API_KEY=sk-...
STRIPE_SECRET_KEY=sk_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_STARTER_PRICE_ID=price_...
STRIPE_PRO_PRICE_ID=price_...
NEXT_PUBLIC_APP_URL=https://your-app.vercel.app
结论
该架构处理了大多数 AI SaaS 需求:使用 Clerk 进行身份验证、Supabase 进行数据持久化、用量计量、Stripe 订阅计费以及 Vercel AI SDK 提供的 AI 功能。对于少于 100 个用户的后端总成本:约 $50/月(Supabase Pro + Vercel Pro + OpenAI 使用量)。盈利所需的收入:3 个 Starter 计划订阅者。
相关教程
使用 TypeScript 和 Vercel AI SDK 在 Next.js 中构建流式 AI 聊天界面、结构化输出和智能体工作流
使用用户级RAG、Edge Functions和流式传输构建全栈AI应用
大规模运行 Assistants API 的工程指南——线程管理、工具使用、文件处理和成本优化
使用现代 Python AI 栈构建生产级 AI 应用
Supabase与pgvector完整集成指南
完整指南:利用OpenAI Assistants API的文件搜索、代码解释器和自定义工具,构建生产级AI客户支持系统