Deployment Philosophy

Moving from local development to production involves coordinating multiple third-party services. Your database, authentication, payments, and storage all need to be pointed to your live domain.

I have structured this guide to ensure you do not miss any critical security or CORS configurations during the launch sequence.

Preparation

Get your codebase ready for the Vercel build engine.

1

Push to GitHub

Ensure your entire project is committed and pushed to a GitHub, GitLab, or Bitbucket repository. Vercel will connect directly to this repository to trigger automatic deployments whenever you push to the main branch.

2

Gather Production Keys

You will need a separate, production-ready Neon database connection string. Do not use your local development database for production. Gather your live Resend keys, live Polar tokens (non-sandbox), and Cloudflare R2 keys.

Vercel Setup

Importing the project and configuring the build environment.

Log in to your Vercel dashboard and click Add New... > Project . Import the repository you just pushed. Vercel will automatically detect that this is a Next.js project and configure the build settings.

Environment Variables

Before clicking Deploy, open the Environment Variables dropdown. You must paste every variable from your local .env file. Be extremely careful to update the following values to their production equivalents:

NEXT_PUBLIC_APP_URL="https://your-production-domain.com"
DATABASE_URL="postgresql://live-user:password@neon-host..."
BETTER_AUTH_SECRET="generate-a-new-random-string"
POLAR_ACCESS_TOKEN="polar_pat_live_token"

Once all variables are added, click Deploy . Vercel will build the project. Do not worry if you cannot log in immediately; we need to run database migrations first.

Database Migration

Syncing your schema to the production Neon Postgres instance.

Your deployed Vercel app is currently pointing to an empty production database. We must push the Drizzle ORM schema to this new instance.

Temporarily swap the DATABASE_URL in your local.env file to match your production database string. Then, run the Drizzle push command from your local terminal:

pnpm drizzle-kit push

Crucial Step: Once the push is successful and the tables are created, immediately revert your local DATABASE_URL back to your local/development database string to prevent accidentally modifying live data!

Post-Deployment Configuration

Updating third-party services to accept requests from your live domain.

Better Auth

OAuth Callbacks (Google & GitHub)

Log in to the Google Cloud Console and GitHub Developer Settings. Update your Authorized Redirect URIs to include your new production domain.

https://your-production-domain.com/api/auth/callback/google
Polar

Polar Webhooks

Turn off Sandbox mode in the Polar dashboard. Recreate your products and create a new webhook pointing to your Vercel deployment. Copy the new Webhook Secret and update your Vercel environment variables.

https://your-production-domain.com/api/webhook/polar
Cloudflare

Cloudflare R2 CORS

Navigate to your R2 Bucket settings and edit the CORS policy. You must explicitly add your production domain to the AllowedOrigins array, otherwise file uploads will silently fail in the browser.

"AllowedOrigins": [
"https://your-production-domain.com",
"http://localhost:3000"
]

Frequently Asked Questions

Why are my images not loading in production?

If you are using the Next.js <Image> component for user avatars or R2 assets, you must whitelist the Cloudflare R2 dev domain in yournext.config.ts file under theremotePatterns array.

Can I deploy this to a VPS instead of Vercel?

Yes. Because this is a standard Next.js application, you can containerize it using Docker or run it directly using PM2 or PM2/Nginx on a DigitalOcean droplet, AWS EC2, or Coolify. You will simply need to build the project using pnpm buildand start it with pnpm start.

Hosting Documentation

Read the official platform guides for advanced CI/CD setups and edge network caching.