TL;DR: A SaaS (Software as a Service) app is a web app people pay a recurring subscription to use. Building one requires four things your AI coding tool can help you with: user accounts (authentication), a place to store data (database), a way to collect money (Stripe billing), and a way to make it live on the internet (deployment). This guide walks through each step with real prompts you can drop straight into Cursor or any AI coding tool.
What You're Actually Building
Before we touch any code, let's be clear about what a SaaS app actually is and what makes it different from a regular website.
A regular website shows information. A SaaS app does something — and it does it for specific users who pay for access. Think of tools like Notion, Loom, or Calendly. They all share the same four-layer structure:
| Layer | What It Does | Tool We'll Use |
|---|---|---|
| Frontend | The pages users see and click on | Next.js (React) |
| Authentication | Sign up, log in, stay logged in | Clerk |
| Database | Store user data, subscriptions, app content | PostgreSQL (via Supabase) |
| Billing | Collect subscription payments | Stripe |
| Deployment | Put it live on the internet | Vercel |
We'll build a simple but real example: a link-in-bio tool. Users sign up, add their social links and a short bio, and get a shareable page. Free users get 3 links; paid users get unlimited links and custom themes. This is simple enough to build in a weekend, complex enough to teach every layer of a real SaaS.
Step 0: Your AI Coding Setup
Before you write a single line of code, get your AI coding environment right. This guide assumes you're using Cursor — it's the AI editor most vibe coders use for projects this size. If you're using VS Code with Copilot, the prompts still work; the workflow is the same.
You'll also need accounts on:
- GitHub — to store your code
- Supabase — free PostgreSQL database hosting
- Clerk — managed authentication (free tier is generous)
- Stripe — payment processing (test mode is free)
- Vercel — deployment (free hobby tier)
Prompt — Project Scaffolding
Create a new Next.js 14 project using the App Router.
Set it up with:
- TypeScript
- Tailwind CSS
- A /app folder structure
- A basic home page at / that says "Welcome to LinkDrop"
- A /dashboard page that's empty for now
Name the project "linkdrop". Show me the exact terminal
commands to run.
Cursor will give you the exact commands. Run them in your terminal. Once your app loads at localhost:3000, you're ready for Step 1.
Step 1: Authentication — Sign Up, Log In, Stay Logged In
Authentication is the system that knows who you are. When a user types their email and password and clicks "Sign In," authentication is what checks those credentials, creates a session, and keeps them logged in as they click around the app.
Building authentication from scratch is notoriously difficult to get right — there are security pitfalls that can take years of experience to recognize. That's why we're using Clerk, a service that handles all of it for you. You get sign-up forms, login pages, password resets, and session management out of the box.
Want to understand what authentication is doing under the hood? Read What Is Authentication? — it explains sessions, tokens, and why rolling your own auth is risky.
Prompt — Install and Configure Clerk
I'm building a Next.js 14 App Router project.
Add Clerk authentication with this setup:
1. Install the @clerk/nextjs package
2. Add ClerkProvider to my root layout.tsx
3. Create a middleware.ts at the project root that
protects /dashboard and all routes under /dashboard/*
4. Add a sign-in button to the navbar that shows
"Sign In" when logged out and the user's first name
when logged in
5. Redirect users to /dashboard after they sign in
My Clerk publishable key is in .env.local as
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY.
Show me every file I need to create or modify.
After running this, your app will redirect any unauthenticated user who tries to visit /dashboard to a Clerk-hosted sign-in page. Once they sign in, they land on the dashboard. That's full authentication — in one prompt.
What "middleware" means here
Middleware runs before a page loads and can decide whether to allow access. It's the bouncer at the door. The middleware.ts file we added checks: "Is this user logged in?" If no, it redirects them to sign in. If yes, it lets them through. You don't need to add that check to every individual page — one middleware file covers everything.
Step 2: Database — Storing Your Users' Data
Every SaaS app needs a place to store information that persists — user profiles, their links, their subscription status. That's what a database is. We're using PostgreSQL, the most widely-used database for web apps. Supabase gives you a free hosted PostgreSQL database with a nice dashboard.
If you want to understand what PostgreSQL is and why it's a good choice, read What Is PostgreSQL?.
For our link-in-bio app, we need two database tables:
- profiles — one row per user, storing their bio, username, and subscription status
- links — one row per link, storing the title, URL, and which user it belongs to
Prompt — Database Schema and API Routes
I'm building a link-in-bio SaaS with Next.js 14 and
PostgreSQL via Supabase. I use Clerk for auth.
Create the following:
1. SQL to create two tables in Supabase:
- profiles: id (uuid), clerk_user_id (text, unique),
username (text, unique), bio (text),
is_pro (boolean, default false),
stripe_customer_id (text),
created_at (timestamp)
- links: id (uuid), profile_id (uuid references
profiles.id), title (text), url (text),
display_order (integer), created_at (timestamp)
2. A /app/api/profile/route.ts with:
- GET: fetch the current user's profile + their links
- POST: create a profile for a new user
3. A /app/api/links/route.ts with:
- GET: return all links for the current user
- POST: create a new link (validate URL format)
- DELETE: delete a link by id
Use the Supabase JS client. The connection string is
in .env.local as DATABASE_URL.
Check Clerk's auth() to get the current user's ID
before any database operation.
This prompt gives you working REST API routes that talk to your database. The key detail in the prompt: "Check Clerk's auth() before any database operation." This is the instruction that ties authentication to data access — ensuring users can only see and modify their own data.
Always check this
When your AI generates database routes, verify that every route that reads or writes data first checks who the logged-in user is. If a route fetches data without that check, any user could access any other user's data. This is the most common security mistake in AI-generated API code.
Step 3: The Dashboard — Where Users Manage Their Stuff
Now that you have auth and a database, build the UI where users actually do things. This is where React comes in — Next.js is built on React, so your pages are made of components (reusable UI pieces).
Prompt — Dashboard UI
Build the /dashboard page for my link-in-bio SaaS.
The dashboard should:
1. Show the user's current links as a list with
a delete button next to each one
2. Show a form to add a new link (title + URL fields,
submit button)
3. Show a "Upgrade to Pro" banner if is_pro is false.
Free users are limited to 3 links — if they have 3
already, disable the add form and show
"Upgrade to Pro to add more links"
4. Fetch data from /api/profile on load
5. After adding or deleting a link, refresh the list
6. Show a loading state while fetching
Use Tailwind CSS. Keep it clean and functional —
no fancy animations needed.
Use TypeScript with proper interfaces for Profile
and Link types.
Notice how the prompt specifies the business rule (free users get 3 links) in plain English. AI tools are good at turning rules like this into real UI logic — but you have to tell them the rule. The AI doesn't know your pricing model; you do.
Step 4: Billing — Getting Paid with Stripe
This is the step most people are most nervous about. Money is involved. But Stripe is genuinely well-designed for developers, and with AI help, the integration is more approachable than it looks.
Here's what Stripe actually does in your app:
- User clicks "Upgrade to Pro"
- Your app creates a Checkout Session — a Stripe-hosted payment page
- User fills in their card details on Stripe's page (not your app — you never touch card numbers)
- Stripe charges the card and sends a webhook — an automatic notification — to your app
- Your app receives the webhook, confirms the payment, and flips
is_prototruein your database
For a deeper look at how Stripe integrations work, see What Is a Stripe Integration?.
Prompt — Stripe Checkout Session
Add Stripe billing to my Next.js 14 SaaS app.
I'm selling a single Pro plan at $9/month.
Create:
1. /app/api/stripe/create-checkout/route.ts
- POST handler
- Gets the current user from Clerk
- Creates a Stripe Checkout Session with:
* mode: "subscription"
* price: my Pro plan price ID from env
(STRIPE_PRO_PRICE_ID)
* success_url: /dashboard?upgraded=true
* cancel_url: /dashboard
* customer_email: the user's email from Clerk
- Returns the checkout URL
2. A "Upgrade to Pro" button component that calls
this endpoint and redirects to the checkout URL
Use the Stripe Node.js SDK. My Stripe secret key
is in STRIPE_SECRET_KEY.
Prompt — Stripe Webhook Handler
Create a Stripe webhook handler at
/app/api/stripe/webhook/route.ts.
It needs to:
1. Verify the webhook signature using
STRIPE_WEBHOOK_SECRET (this prevents fake requests)
2. Handle the "checkout.session.completed" event:
- Get the customer's email from the event
- Find the profile in my database where the
email matches
- Set is_pro = true for that profile
- Set stripe_customer_id to the Stripe customer ID
3. Handle "customer.subscription.deleted":
- Find the profile by stripe_customer_id
- Set is_pro = false
Use the Supabase JS client for database updates.
IMPORTANT: The webhook route must export a config
that disables body parsing, or Stripe signature
verification will fail. Show me exactly how to
do this in Next.js 14 App Router.
Test mode vs. live mode
Stripe has two modes: test and live. In test mode, use card number 4242 4242 4242 4242 (any future expiry, any CVC) to simulate payments. No real money moves. Switch to live mode only when you're ready to accept real payments from real customers. Always develop and test in test mode first.
Step 5: The Public Profile Page
Every link-in-bio tool needs a public page at a URL like yourdomain.com/username. This is what users share with their audience. It's the product people actually see.
Prompt — Dynamic Public Profile Page
Create a dynamic public profile page at
/app/[username]/page.tsx.
This page should:
1. Accept a username from the URL parameter
2. Query the database for the profile where
username matches
3. If no profile found, show a 404 page
4. If found, display:
- The user's bio
- All their links as clickable buttons
- A small "Powered by LinkDrop" footer link
5. Use generateMetadata to set the page title to
"[Username]'s links | LinkDrop" for SEO
6. This page should be server-rendered (no
"use client") so it loads fast and gets indexed
by Google
Use Tailwind CSS. Make it clean and mobile-first —
most visitors will be on their phones.
Step 6: Deployment — Making It Live
You have a working app running on your laptop. Now you need to put it somewhere the rest of the world can access it. Vercel is the answer — it was built by the same team that created Next.js, so the integration is seamless.
The deployment process:
- Push your code to a GitHub repository
- Go to vercel.com, click "Import Project," and connect your GitHub repo
- Add your environment variables (all the secret keys) in the Vercel dashboard
- Click "Deploy"
Environment variables checklist
Before deploying, make sure every key from your local .env.local file is added to Vercel's environment variables. Missing keys are the #1 reason apps that work locally break in production.
Prompt — Pre-Deployment Checklist
I'm about to deploy my Next.js 14 SaaS app to Vercel.
The app uses Clerk auth, Supabase PostgreSQL, and
Stripe billing.
Generate a pre-deployment checklist that covers:
1. Every environment variable I need to set in Vercel
2. Stripe webhook URL — what URL do I register in
the Stripe dashboard after deployment?
3. Clerk allowed redirect URLs — what do I need
to update in Clerk for my production domain?
4. Supabase connection — do I need to add my
Vercel deployment URL to any allow-list?
5. A quick test plan: what 5 things should I test
first after deploying to make sure nothing is broken?
After you get your Vercel deployment URL (something like linkdrop.vercel.app), go into your Stripe dashboard and update your webhook endpoint to https://linkdrop.vercel.app/api/stripe/webhook. This is the step people most often forget, and it means subscriptions don't activate in production.
What Can Go Wrong (and How AI Helps)
Building a SaaS always surfaces unexpected problems. Here are the most common ones and the prompts that fix them:
Stripe webhooks are not triggering
Debugging Prompt
My Stripe webhook at /api/stripe/webhook is not
receiving events in production. In development it
works fine with the Stripe CLI.
Here is my webhook route code: [paste code]
What are the most likely reasons a Next.js App Router
webhook route would receive events locally but not
in production on Vercel? Check for: body parsing
config, signature verification, environment variable
names, and HTTPS requirements.
Users can see each other's data
Security Audit Prompt
Review my API routes and identify any places where
a logged-in user could access or modify another
user's data.
Here are my API route files: [paste files]
For each route, confirm:
1. Is the user's Clerk ID being checked?
2. Is the database query filtered by that user's ID?
3. Could someone craft a request to access
a different user's records?
Show me any vulnerable routes and the fix for each.
The Stack, Summarized
Here's every tool you used and what it's responsible for:
| Tool | Role in Your SaaS | Free Tier? |
|---|---|---|
| Next.js | Pages, routing, API endpoints | ✅ Open source |
| Clerk | User sign up, login, sessions | ✅ Free up to 10k MAU |
| Supabase | Hosted PostgreSQL database | ✅ Free tier available |
| Stripe | Payment processing, subscriptions | ✅ Free (pay per transaction) |
| Vercel | Deploy and host the app | ✅ Free hobby tier |
Total monthly cost for an early-stage SaaS: $0 until you hit meaningful scale. That's the real unlock. You can build, launch, and validate your idea without spending anything on infrastructure until you're making money.
Frequently Asked Questions
Yes — with important caveats. AI coding tools like Cursor can generate working code from plain-English descriptions, which means you can get surprisingly far without a CS background. The catch: you still need to understand what the pieces do (auth, database, billing) so you can give good instructions and catch mistakes. This guide is designed to give you that foundational understanding in plain language.
For vibe coders in 2026, a strong starting stack is: Next.js (React framework) for the frontend and API routes, PostgreSQL (via Supabase) for the database, Clerk for authentication, Stripe for billing, and Vercel for deployment. This stack has excellent documentation, a massive community, and AI tools like Cursor are extremely good at generating code for it — which matters a lot when you're building with AI as your main coding partner.
Authentication is the system that lets users sign up, log in, and stay logged in. For a SaaS app, you have two solid options: use a managed auth service like Clerk (fastest to set up, handles everything for you including password resets and session management) or use NextAuth.js (open-source, more control, runs inside your own app). For first-time builders, Clerk reduces the complexity significantly — you give your AI the integration instructions and it handles the hard security parts.
Stripe handles the payment side so you never have to touch credit card numbers. You create a subscription product and price in your Stripe dashboard, then add code that creates a Checkout Session when a user clicks "Subscribe." The user fills in their card on Stripe's hosted page, Stripe charges them, then sends a webhook notification to your app confirming the payment. Your app receives that webhook and unlocks the paid features for that user. The Stripe CLI lets you test the full flow locally without real money.
A webhook is a way for an external service (like Stripe) to automatically notify your app when something happens — a payment succeeds, a subscription is cancelled, a card expires. Instead of your app constantly asking "did anything happen?", Stripe sends a POST request to a special URL on your app the moment an event fires. Your app listens at that URL and updates its database in response. Every SaaS with billing needs at least webhook handlers for payment success and subscription cancellation.
Vercel is the easiest deployment option for Next.js apps — it was built by the same team that created Next.js. Connect your GitHub repository to Vercel, set your environment variables (Clerk keys, Stripe keys, database URL) in the Vercel dashboard, and click deploy. Every subsequent push to your main branch automatically triggers a new deployment. A basic app can be live in under 10 minutes from first push, and the free hobby tier covers everything you need at early stage.
What to Learn Next
You now have a complete mental map of what it takes to build a SaaS app with AI. Here's where to go deeper on each piece:
🔐 Auth
What Is Authentication?How sign-in systems actually work: sessions, tokens, JWTs, and why building auth from scratch is risky.
💳 Stripe
What Is a Stripe Integration?Checkout sessions, webhooks, subscriptions, and the full billing lifecycle explained in plain English.
🐘 Database
What Is PostgreSQL?Why PostgreSQL is the go-to database for web apps, and what tables, rows, and queries actually mean.
🚀 Deploy
What Is Vercel?How Vercel deploys Next.js apps, what edge functions are, and how to set environment variables in production.
⚛️ React
What Is React?Components, props, state — the building blocks of every Next.js UI. Explained without the jargon.
🔌 APIs
What Is a REST API?GET, POST, DELETE — what the API routes you built in this guide are actually doing and why they're designed that way.
Also useful as you keep building:
- Cursor Beginner's Guide — The AI editor this whole guide assumed you were using
The real lesson here
The hard part of building a SaaS with AI is not the code — it's knowing what to ask for. AI will write the Stripe webhook handler, the authentication middleware, and the database queries. Your job is to understand each layer well enough to give precise instructions, review what comes back, and catch the mistakes. That's a skill you build quickly. The first SaaS is the hardest. The second one takes half as long.