A Next.js 14 project scaffolded with the full SaaS stack: Prisma connected to a database, NextAuth for authentication, Stripe configured in test mode, and a Claude-powered feature behind a paywall.
The SaaS Stack Explained
A production AI SaaS has six layers. Every decision you make flows from understanding these layers and how they connect.
Scaffold the Project
Create the Next.js app and install all dependencies at once. This is the full stack for a production AI SaaS.
# Create Next.js app
npx create-next-app@latest ai-saas --typescript --tailwind --app --src-dir
cd ai-saas
# Install all dependencies
npm install @prisma/client prisma next-auth @auth/prisma-adapter stripe @stripe/stripe-js anthropic bcryptjs @types/bcryptjs
# Init Prisma
npx prisma init --datasource-provider postgresql# Database
DATABASE_URL="postgresql://..."
# Auth
NEXTAUTH_SECRET="..."
NEXTAUTH_URL="http://localhost:3000"
GOOGLE_CLIENT_ID="..."
GOOGLE_CLIENT_SECRET="..."
# Stripe
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_WEBHOOK_SECRET="whsec_..."
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_..."
# AI
ANTHROPIC_API_KEY="sk-ant-..."The Database Schema
The Prisma schema is the heart of your SaaS. Get it right from the start — adding columns later is easy, but changing relationships is painful.
model User {
id String @id @default(cuid())
email String @unique
name String?
password String? // null for OAuth users
stripeCustomerId String? @unique
plan Plan @default(FREE)
creditsUsed Int @default(0)
creditsLimit Int @default(10) // 10/mo free
generations Generation[]
createdAt DateTime @default(now())
}
model Generation {
id String @id @default(cuid())
userId String
prompt String
result String
tokens Int
user User @relation(fields: [userId], references: [id])
createdAt DateTime @default(now())
}
enum Plan { FREE PRO ENTERPRISE }npx prisma migrate dev --name initThe Route Structure
Organizing routes well from the start prevents the spaghetti that kills most SaaS projects. Here's the structure for a typical AI SaaS.
src/app/
├── (marketing)/ ← route group: no URL segment
│ ├── page.tsx → / (landing page)
│ ├── pricing/page.tsx → /pricing
│ └── layout.tsx ← marketing nav/footer
├── (auth)/
│ ├── login/page.tsx → /login
│ └── register/page.tsx → /register
├── dashboard/ ← protected by middleware
│ ├── layout.tsx ← sidebar layout
│ ├── page.tsx → /dashboard
│ ├── generate/page.tsx → /dashboard/generate (AI feature)
│ └── settings/page.tsx → /dashboard/settings
└── api/
├── auth/[...nextauth]/ ← NextAuth
├── generate/route.ts ← Claude API call
├── stripe/checkout/ ← create checkout session
└── webhooks/stripe/ ← receive Stripe eventsWhat You Learned Today
- Understood the six-layer SaaS stack and how Next.js, Prisma, Auth, Stripe, Claude, and Vercel connect
- Scaffolded the project with all dependencies installed and environment variables configured
- Designed a schema with User, Generation, and Plan enum — covering billing, usage tracking, and AI output storage
- Organized routes into marketing, auth, dashboard, and API groups for clean separation
Go Further on Your Own
- Add a Subscription model to track Stripe subscription IDs, periods, and cancellation status
- Create the middleware.ts file that redirects unauthenticated users from /dashboard to /login
- Set up Prisma Studio with npx prisma studio and explore the empty tables
Nice work. Keep going.
Day 2 is ready when you are.
Continue to Day 2Want live instruction and hands-on projects? Join the AI bootcamp — 3 days, 5 cities.