Claude Code Boilerplate
FeaturesPricingBlogDocs
Get started →

Product

  • Features
  • Pricing
  • Skills

Compare

  • vs ShipFast
  • vs MakerKit
  • vs supastarter

Resources

  • Docs
  • Blog
  • Discord

Legal

  • License
  • Privacy Policy
  • Terms of Service
Claude Code Boilerplate

© 2026 Claude Code Boilerplate. All rights reserved.

← All posts

How to Deploy Your Next.js SaaS to Vercel -- Environment Variables, Database Migrations, and a Smooth First Launch

September 6, 2026
nextjsvercelneon-dbdeploymentsaas

You have been running npm run dev for weeks. The app works on your machine. Payments process, emails send, logins work. Then you push to Vercel and something breaks -- a missing environment variable, a database that worked locally but times out in production, or a cold-start error you have never seen before.

This is the most common "done but not launched" trap. You are not missing features. You are missing the 45 minutes it takes to set up production correctly.

Here is the exact sequence.

Step 1: Connect Your Repository to Vercel

If you are using the Next.js SaaS Boilerplate, your code is already on GitHub. Go to vercel.com, create a new project, and import the repository. Vercel detects Next.js automatically and sets the build command to npm run build -- you do not need to change the framework preset.

Once the repo is connected:

  • Every push to main triggers a production deployment
  • Every push to any other branch creates a preview deployment at a unique URL

That second point is not a nice-to-have. It means every pull request gets a live URL before anything touches production. You get a staging environment for free.

Step 2: Set Your Environment Variables

Your local .env file never goes to Vercel -- that is intentional, because it contains secrets. You have to add each variable manually in your Vercel project under Settings -> Environment Variables.

At a minimum, add these:

JWT_SECRET=<a long random string -- never reuse the local one>
DATABASE_URL=<your Neon DB production pooled connection string>
NEXT_PUBLIC_BASE_URL=https://yourdomain.com
RESEND_API_KEY=<from resend.com>
CLOUDINARY_CLOUD_NAME=<from cloudinary.com>
CLOUDINARY_API_KEY=<from cloudinary.com>
CLOUDINARY_API_SECRET=<from cloudinary.com>
STRIPE_SECRET_KEY=<your Stripe live secret key>
STRIPE_PUBLISHABLE_KEY=<your Stripe live publishable key>
STRIPE_WEBHOOK_SECRET=<from Stripe webhook dashboard>

Two variables need extra attention.

DATABASE_URL for serverless. Neon gives you two connection strings: a regular one and a pooled one. For Vercel, which runs serverless functions that spin up and down constantly, you want the pooled connection string from the "Pooled connection" section of your Neon dashboard. It ends in ?sslmode=require. Using the regular string means every cold start opens a new database connection, and you will hit Neon's connection limit under any real load.

Neon also has a first-party Vercel integration that sets DATABASE_URL automatically when you link the projects -- worth using if you want to skip this manual step.

NEXT_PUBLIC_BASE_URL. Set this to your production URL including https://. Variables prefixed with NEXT_PUBLIC_ are embedded at build time, not at request time. If this is wrong, every OG image, email confirmation link, and canonical URL in your app points to the wrong domain.

Step 3: Run Database Migrations

Your Neon DB schema does not exist in production yet. Migrations you ran locally created tables in your local or development database branch -- not in production.

Before real users land, run this once against your production database:

DATABASE_URL="<your production connection string>" npm run db:migrate

Vercel does not run this automatically. It is a manual step you repeat whenever a schema change reaches production.

The db:push command (npm run db:push) is a shortcut that skips migration files and syncs the schema directly. It is fine in early development, but switch to db:migrate before you have real user data -- migration files give you a reversible history of schema changes.

Step 4: Add Your Custom Domain

In your Vercel project -> Settings -> Domains, add your domain. Vercel gives you two DNS records to add at your registrar: an A record and a CNAME. SSL is provisioned automatically within a few minutes.

After the domain is live, update NEXT_PUBLIC_BASE_URL in your Vercel environment variables to match the real domain, then redeploy by pushing a commit to main.

Step 5: Register Your Stripe Webhook

If you are using Stripe, your local webhook listener was hitting localhost. Production needs its own endpoint.

Go to Stripe Dashboard -> Developers -> Webhooks -> Add endpoint. Use:

https://yourdomain.com/api/webhooks/stripe

Select the events your app handles. At minimum: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, and invoice.payment_failed.

Copy the webhook secret Stripe generates and add it as STRIPE_WEBHOOK_SECRET in Vercel, then redeploy.

Without this step, Stripe will process payments but your app will never know about them. Plan upgrades, subscription cancellations, and failed payment recovery all break silently.

How to Know It Worked

Run three end-to-end checks after your first production deploy:

  1. Sign up as a new user and confirm the welcome email arrives
  2. Complete a Stripe checkout and verify your plan updates in the app
  3. Log out, then log back in from an incognito window

If any of those fail, the problem is almost always a missing or incorrect environment variable -- not the code itself.

For a broader pre-launch checklist beyond the deploy, see The SaaS Launch Checklist.

The Gap Between Working and Live

A working local dev environment is not a launched product. The distance between the two is smaller than most founders expect -- usually two or three hours of environment setup, not another sprint of features.

If you are starting fresh, the Next.js SaaS Boilerplate gives you a codebase that deploys to Vercel on day one, with auth, payments, and email already configured. You spend your first weekend on your actual product idea, not on infrastructure.

Get it live. Real users will tell you what to build next.