How to deploy a Next.js app from a GitHub repo, with its database
Create a production Postgres database, import the GitHub repository into a host that runs Node.js, add the environment variables from .env.example, set the build to run database migrations before next build, then seed the first account and test every form. Most failed first deploys are a missing variable or a database that was never migrated.
Choose where it runs
Next.js's deployment documentation lists four routes: a Node.js server, a Docker container, a static export, or a platform adapter. A Node.js server and Docker support every feature; a static export drops anything that needs a server, which rules it out for an app with forms and sign-in.
| Option | Effort | Suits |
|---|---|---|
| Vercel | Import the repo, add variables, deploy | Getting live quickly; automatic deploys on every push |
| Other platforms with Next.js support (Netlify, Cloudflare and others) | Similar, with each platform's own integration | If you already use that platform; check feature support |
| A Node.js host or VPS | Run npm run build then npm run start behind a process manager | Full control, predictable cost |
| Docker | Build an image, run it anywhere containers run | Teams already using containers |
Before you start
- The code is in a GitHub repository you control. If it came from Anticode, push it to GitHub first.
- It runs locally.
npm install,npm run devand a working form on your own machine save hours of guessing on the host. - You have a production database. Hosted Postgres from Neon or Supabase is the quickest; copy its connection string. Use a separate database from the one you developed against.
Deploy it, step by step (Vercel example)
Here's how to deploy a Next.js app on Vercel; the same order of work applies on other hosts.
- Create the database at your Postgres provider and copy the connection string, including
?sslmode=requireif the provider gives it. - Import the repository in the host's dashboard and let it detect Next.js.
- Add the environment variables for the Production environment. Open
.env.examplein the repo and add every name listed there with its production value. On Vercel, variable changes apply only to new deployments, as its environment variable docs note, so redeploy after editing them. - Set the build command so migrations run first. For a Prisma app that's
prisma migrate deploybefore the build; the Anticode export's README givesnpm run db:deploy && npm run build. - Deploy and read the build log to the end. A Prisma or database error here usually means a wrong
DATABASE_URLor a database that refuses outside connections. - Seed the first account once, from your machine, pointing at the production database, then remove any password variables used only for seeding.
- Connect your domain in the host's domain settings with the DNS records it shows, and update the app's own public URL variable to match.
- Test the live app: each form, sign-in, the admin area and an email, on a phone.
Deploying an Anticode Next.js export
Anticode exports a standard Next.js (App Router) project with TypeScript, Postgres through Prisma and Zod, server routes for bookings, contact, newsletter and email sign-in, and an admin area with two-factor sign-in and roles. It has no Anticode runtime, so it deploys like any other Next.js app. Its README covers Neon, Supabase, Docker and Vercel. The variables it expects are listed in .env.example:
DATABASE_URL- The Postgres connection string.
APP_URL- The public address, used in email links and the same-origin check on forms. A mismatch here makes every form post fail.
ENCRYPTION_KEY- 32 random bytes in base64, used to encrypt two-factor secrets. Changing it later resets everyone's two-factor sign-in.
OWNER_EMAIL,OWNER_PASSWORD- The first owner account, created by
npm run db:seed. Remove the password afterwards. RESEND_API_KEY,EMAIL_FROM,NOTIFY_EMAIL- Email through Resend and where alerts go. Without a key, emails are printed to the log instead of sent.
SLOT_CAPACITY- How many bookings one time slot can hold.
The migrations also create Postgres row-level security policies, so run them with the provided script rather than pushing the schema another way. Once exported, the app is yours to run: Anticode's own hosting, backups, form connectors and analytics don't apply to it.
When it works locally but not in production
- A variable is missing or set only for Preview. Check the Production scope.
- The build ran before migrations, so tables don't exist. Check the build command order.
- The public URL doesn't match the domain, so same-origin checks reject form posts. Update it after connecting the domain.
- The database blocks connections from the host's region or needs SSL. Check the provider's network settings.
- Secrets in the wrong place. Variables prefixed
NEXT_PUBLIC_are sent to the browser; API keys in frontend code explains why secrets must never use that prefix.
Limits
A deployed app needs looking after: dependency updates, database backups, watching logs and renewing the domain. Free tiers of hosts and databases often pause or limit inactive projects, so read their terms before relying on one for customers. Running it is now a developer's job, which when to move to custom code weighs up.
Questions people ask
Can I deploy Next.js without Vercel?
Yes. Any host that runs Node.js, or Docker, supports every Next.js feature. Vercel is a convenient option, not a requirement.
Do I run migrations on every deploy?
Running the deploy-migrations command on every build is safe: it applies only migrations that haven't run yet.
Why are my emails not sending after deploy?
Usually the email API key isn't set for Production, or the sending domain isn't verified with the email provider.
Sources
- Deploying (Next.js docs), checked
- Environment variables (Vercel docs), checked