从账号注册→环境配置→代码开发→部署上线全流程拆解,覆盖每个工具的关键操作、避坑点及核心代码示例。
📋 前期准备(必做)
1. 工具账号注册(按优先级)
工具 注册入口 关键操作 避坑点
GitHub https://github.com 注册→绑定邮箱→创建私人令牌(Settings/Developer settings) 令牌权限仅给repo和user,避免过度授权
Cloudflare https://dash.cloudflare.com 注册→添加域名→修改DNS服务器为Cloudflare提供的 免费版已包含CDN/SSL,无需升级付费
Namecheap https://www.namecheap.com 搜索域名→购买(推荐.xyz/.app低价后缀)→解析到Cloudflare 首次购买用优惠码,最低可至$8/年
Claude Pro https://www.anthropic.com 注册→付费$20/月 仅需基础版,满足代码生成/调试即可
Supabase https://supabase.com 注册→创建新Project→设置数据库密码 免费版有500MB存储,足够MVP阶段
Vercel https://vercel.com GitHub授权登录→无需额外注册 自动关联GitHub仓库,一键部署
其余工具(Resend/Clerk/Stripe等) 对应官网 GitHub一键授权注册 均选择免费套餐,后续按需升级
2. 本地开发环境配置
1. 安装依赖(Python/Node.js):
# 安装Node.js(推荐20.x版本)
brew install node # Mac
# Windows从官网下载安装 https://nodejs.org/
# 安装pnpm(比npm/yarn更快)
npm install -g pnpm
# 安装Python(推荐3.10+)
brew install python # Mac
# Windows从官网下载安装 https://www.python.org/
2. 初始化Next.js项目(前端框架):
pnpm create next-app@latest my-saas --typescript --tailwind --app
cd my-saas
# 安装核心依赖
pnpm add @clerk/nextjs @supabase/supabase-js resend stripe @sentry/nextjs posthog
⚙️ 核心工具配置与代码集成(分模块)
模块1:域名与网络(Cloudflare + Namecheap)
1. 域名解析配置
1. 登录Namecheap→进入你的域名管理页→Nameservers→选择Custom DNS
2. 粘贴Cloudflare提供的2个DNS服务器地址(如ns1.cloudflare.com/ns2.cloudflare.com)→保存
3. 登录Cloudflare→进入域名→DNS→添加2条记录:
◦ 类型A:名称@,内容192.0.2.1(临时值,后续Vercel部署后替换)
◦ 类型CNAME:名称www,内容你的域名.com
2. SSL配置(避坑关键)
Cloudflare自动开启SSL,需设置为Full模式:
Cloudflare→SSL/TLS→Overview→SSL加密模式→选择Full(避免混合内容错误)。
模块2:后端与数据库(Supabase + Upstash + Pinecone)
1. Supabase配置(核心数据库)
(1)数据库创建
Supabase→新建Project→填写项目名/密码→创建完成后进入SQL Editor→新建查询,创建基础表(示例:用户表+产品表):
-- 创建用户表(关联Clerk用户ID)
CREATE TABLE public.profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
username TEXT UNIQUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 创建产品表
CREATE TABLE public.products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
price DECIMAL(10,2) NOT NULL,
description TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 开启行级安全(RLS)
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.products ENABLE ROW LEVEL SECURITY;
-- 仅允许用户查看自己的资料
CREATE POLICY "用户查看自己资料" ON public.profiles
FOR SELECT USING (auth.uid() = id);
(2)代码集成(Next.js)
在项目根目录创建.env.local,填入Supabase密钥:
# Supabase
NEXT_PUBLIC_SUPABASE_URL=你的Supabase项目URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=你的匿名密钥
创建lib/supabase.ts(封装Supabase客户端):
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
// 示例:获取产品列表
export async function getProducts() {
const { data, error } = await supabase
.from('products')
.select('*')
.order('created_at', { ascending: false });
if (error) throw new Error(error.message);
return data;
}
2. Upstash(Redis)配置(缓存/队列)
1. Upstash→新建Redis数据库→选择Free Plan→复制REST API地址和令牌
2. .env.local添加配置:
UPSTASH_REDIS_REST_URL=你的Upstash地址
UPSTASH_REDIS_REST_TOKEN=你的Upstash令牌
3. 安装Upstash SDK:pnpm add @upstash/redis
4. 代码示例(缓存产品数据):
import { Redis } from '@upstash/redis';
const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
// 缓存产品列表(有效期10分钟)
export async function getProductsWithCache() {
// 先查缓存
const cached = await redis.get('products:list');
if (cached) return JSON.parse(cached);
// 缓存未命中,查数据库
const products = await getProducts();
// 写入缓存
await redis.set('products:list', JSON.stringify(products), { ex: 600 });
return products;
}
3. Pinecone(向量数据库)配置(AI功能)
1. Pinecone→新建项目→选择Starter Plan→创建索引(维度根据你的向量模型调整,如1536)
2. .env.local添加配置:
PINECONE_API_KEY=你的Pinecone密钥
PINECONE_INDEX_NAME=你的索引名
PINECONE_ENVIRONMENT=你的环境名(如gcp-starter)
3. 代码示例(向量存储与检索):
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone({
apiKey: process.env.PINECONE_API_KEY!,
});
const index = pinecone.Index(process.env.PINECONE_INDEX_NAME!);
// 存储向量
export async function storeVector(id: string, vector: number[], metadata: any) {
await index.upsert([
{
id,
values: vector,
metadata,
},
]);
}
// 检索相似向量
export async function queryVector(vector: number[], topK: number = 5) {
const results = await index.query({
vector,
topK,
includeMetadata: true,
});
return results.matches;
}
模块3:用户认证(Clerk)
1. Clerk配置
1. Clerk→新建应用→选择Next.js框架→复制Publishable Key和Secret Key
2. .env.local添加配置:
# Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=你的Clerk公钥
CLERK_SECRET_KEY=你的Clerk私钥
# 登录/注册回调地址
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
2. 代码集成(Next.js)
(1)配置Clerk提供者
修改app/layout.tsx,包裹Clerk组件:
import { ClerkProvider } from '@clerk/nextjs';
import './globals.css';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<ClerkProvider>
<html lang="zh-CN">
<body>{children}</body>
</html>
</ClerkProvider>
);
}
(2)创建登录/注册页面
新建app/sign-in/[[...sign-in]]/page.tsx:
import { SignIn } from '@clerk/nextjs';
export default function SignInPage() {
return (
<div className="flex justify-center items-center min-h-screen">
<SignIn />
</div>
);
}
新建app/sign-up/[[...sign-up]]/page.tsx:
import { SignUp } from '@clerk/nextjs';
export default function SignUpPage() {
return (
<div className="flex justify-center items-center min-h-screen">
<SignUp />
</div>
);
}
(3)路由守卫(未登录用户拦截)
新建middleware.ts(项目根目录):
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
// 定义需要登录的路由
const protectedRoutes = createRouteMatcher([
'/dashboard(.*)',
'/product(.*)',
'/checkout(.*)',
]);
export default clerkMiddleware((auth, req) => {
if (protectedRoutes(req)) {
auth().protect();
}
});
export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};
模块4:业务功能集成(Resend/Stripe/Sentry/PostHog)
1. 邮件发送(Resend)
(1)Resend配置
1. Resend→添加域名→验证域名(添加TXT记录到Cloudflare)
2. 复制API Key→.env.local添加:
RESEND_API_KEY=你的Resend密钥
RESEND_FROM_EMAIL=验证后的邮箱(如no-reply@你的域名)
(2)代码示例(发送欢迎邮件)
新建app/api/send-welcome/route.ts:
import { Resend } from 'resend';
import { currentUser } from '@clerk/nextjs/server';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST() {
try {
const user = await currentUser();
if (!user) return new Response('未登录', { status: 401 });
const { data, error } = await resend.emails.send({
from: `你的项目 <${process.env.RESEND_FROM_EMAIL}>`,
to: user.emailAddresses[0].emailAddress,
subject: '欢迎使用你的项目!',
html: `
<h1>欢迎,${user.firstName}!</h1>
<p>感谢你注册我们的服务,开始探索你的第一个SaaS产品吧!</p>
`,
});
if (error) throw new Error(error.message);
return Response.json({ data });
} catch (error) {
return new Response('发送失败', { status: 500 });
}
}
2. 支付系统(Stripe)
(1)Stripe配置
1. Stripe→测试模式→创建产品(如基础版$9.9/月)→复制Publishable Key和Secret Key
2. .env.local添加配置:
# Stripe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=你的Stripe公钥
STRIPE_SECRET_KEY=你的Stripe私钥
STRIPE_WEBHOOK_SECRET=你的Webhook密钥(后续配置)
(2)代码示例(创建支付链接)
新建app/api/create-checkout/route.ts:
import Stripe from 'stripe';
import { currentUser } from '@clerk/nextjs/server';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2024-06-20',
});
export async function POST() {
try {
const user = await currentUser();
if (!user) return new Response('未登录', { status: 401 });
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: 'usd',
product_data: { name: '基础版会员' },
unit_amount: 999, // $9.9
},
quantity: 1,
},
],
mode: 'subscription',
success_url: `${process.env.NEXT_PUBLIC_APP_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/pricing`,
customer_email: user.emailAddresses[0].emailAddress,
});
return Response.json({ url: session.url });
} catch (error) {
return new Response('创建支付失败', { status: 500 });
}
}
(3)前端调用支付
新建app/pricing/page.tsx:
'use client';
import { useRouter } from 'next/navigation';
export default function PricingPage() {
const router = useRouter();
const handleCheckout = async () => {
const res = await fetch('/api/create-checkout', { method: 'POST' });
const { url } = await res.json();
router.push(url);
};
return (
<div className="max-w-md mx-auto mt-10">
<h1 className="text-2xl font-bold">会员价格</h1>
<p className="mt-4">基础版:$9.9/月</p>
<button
onClick={handleCheckout}
className="mt-6 bg-blue-600 text-white px-6 py-2 rounded-lg"
>
立即开通
</button>
</div>
);
}
3. 错误追踪(Sentry)
(1)Sentry配置
1. Sentry→新建项目→选择Next.js→复制DSN
2. .env.local添加:
NEXT_PUBLIC_SENTRY_DSN=你的Sentry DSN
SENTRY_AUTH_TOKEN=你的Sentry授权令牌(项目设置中获取)
(2)代码集成
修改app/layout.tsx,添加Sentry初始化:
import * as Sentry from '@sentry/nextjs';
import { ClerkProvider } from '@clerk/nextjs';
import './globals.css';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
});
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<ClerkProvider>
<html lang="zh-CN">
<body>{children}</body>
</html>
</ClerkProvider>
);
}
4. 产品分析(PostHog)
(1)PostHog配置
1. PostHog→新建项目→复制API Key
2. .env.local添加:
NEXT_PUBLIC_POSTHOG_KEY=你的PostHog密钥
NEXT_PUBLIC_POSTHOG_HOST=https://us.posthog.com
(2)代码集成
修改app/layout.tsx,添加PostHog组件:
import { PostHogProvider } from 'posthog-js/react';
import { ClerkProvider } from '@clerk/nextjs';
import './globals.css';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
评论
发表评论