Anticode Open builder

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.

Updated · By the Anticode team

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.

Common choices for a small Next.js app with a database
OptionEffortSuits
VercelImport the repo, add variables, deployGetting live quickly; automatic deploys on every push
Other platforms with Next.js support (Netlify, Cloudflare and others)Similar, with each platform's own integrationIf you already use that platform; check feature support
A Node.js host or VPSRun npm run build then npm run start behind a process managerFull control, predictable cost
DockerBuild an image, run it anywhere containers runTeams 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 dev and 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.

  1. Create the database at your Postgres provider and copy the connection string, including ?sslmode=require if the provider gives it.
  2. Import the repository in the host's dashboard and let it detect Next.js.
  3. Add the environment variables for the Production environment. Open .env.example in 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.
  4. Set the build command so migrations run first. For a Prisma app that's prisma migrate deploy before the build; the Anticode export's README gives npm run db:deploy && npm run build.
  5. Deploy and read the build log to the end. A Prisma or database error here usually means a wrong DATABASE_URL or a database that refuses outside connections.
  6. Seed the first account once, from your machine, pointing at the production database, then remove any password variables used only for seeding.
  7. 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.
  8. 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

  1. Deploying (Next.js docs), checked
  2. Environment variables (Vercel docs), checked