Skip to Content
React in a Week
Day 7 · Production with Next.js

Deploy to Vercel

Build the Reading List for production, put it on GitHub, and deploy it to a public URL with Vercel's Git integration or the Vercel CLI.

An app on your laptop is a prototype. An app at a URL you can send to a friend is a project. Deploying means building your app for production and running it on a server that anyone on the internet can reach.

Next.js runs anywhere you can run Node.js, so you have many choices. This lesson uses Vercel, the company that makes Next.js, because it needs no server setup and its free Hobby plan is enough for personal projects. The first two steps, building locally and pushing to GitHub, are the same for any host.

Build it locally first

The dev server is forgiving. A production build checks your types, runs the prerendering from the caching lesson, and fails loudly on errors. It is much nicer to see those errors on your laptop than in a deploy log.

npm run build

At the end, Next.js prints a table of your routes and how each one was rendered, for example which parts were prerendered and which are rendered on request. If the build fails, the message names the file and usually suggests a fix.

Then run the production build on your machine:

npm start

Open http://localhost:3000 and try the app again. This is the same code that will run on the server, minus the development warnings.

npm run lint is also worth running before every deploy. Since Next.js 16, next build no longer runs ESLint for you.

Put the code on GitHub

create-next-app already made your project a Git repository with a first commit. You need a free GitHub account for the next steps.

Commit your work

git add .
git commit -m "Reading List on Next.js"

The .gitignore from create-next-app already keeps node_modules, .next and .env* files out of Git.

Create an empty repository on GitHub

On github.com, choose New repository, name it reading-list-next, and leave the options to add a README or .gitignore unticked, because your project already has them.

Push

GitHub shows the commands to copy. They look like this, with your username:

git remote add origin https://github.com/your-username/reading-list-next.git
git branch -M main
git push -u origin main

Deploy by importing from GitHub

Sign up and import

Go to vercel.com and sign up with your GitHub account. Then open vercel.com/new, find reading-list-next in the list of repositories, and choose Import. You may need to give Vercel permission to see that repository first.

Check the settings and deploy

Vercel detects that this is a Next.js app and fills in the build settings, so you don't need to change anything. Choose Deploy. The build runs in the cloud and takes a minute or two.

Open your URL

When it finishes you get a URL like reading-list-next.vercel.app. That is your app, live on the internet.

From now on, Git drives your deploys:

  • Every push to main creates a new production deployment at your main URL.
  • Every push to any other branch, and every pull request, creates a preview deployment with its own URL. You can try a change, or share it for feedback, before it reaches production.
Quick check

You push a branch called add-ratings to GitHub, and the project is connected to Vercel. What happens?

Deploy from the terminal with the Vercel CLI

The Git flow is the one you will use most. Sometimes it is handy to deploy straight from your machine, for example before you have set up GitHub. The Vercel CLI does that.

Install and log in

npm install -g vercel
vercel login

Make a preview deployment

From the project folder, run:

vercel

The first time, it asks a few questions to link the folder to a Vercel project. The defaults are fine. It uploads your code, builds it in the cloud, and prints a preview URL.

Deploy to production

vercel --prod

This builds and deploys to your production URL.

You can mix the two approaches. A project linked to GitHub still accepts CLI deploys.

Keep secrets in environment variables

The Reading List doesn't have any secrets yet. As soon as it talks to a real database or API, it will have a connection string or an API key. Those must never be written in your code or committed to Git.

Put them in environment variables instead:

  • Locally, in a .env.local file in the project root. Next.js loads it automatically, and the default .gitignore keeps it out of Git.
  • On Vercel, in your project's Settings, under Environment Variables. You can set different values for production and preview. If you use the CLI, vercel env pull downloads them into a local file for development.
.env.local
DATABASE_URL=postgres://user:password@host/db
lib/books.ts
const url = process.env.DATABASE_URL; // only available on the server

Server code, such as Server Components and Server Functions, can read any variable. Only variables whose names start with NEXT_PUBLIC_ are copied into the browser's JavaScript, so never give a secret that prefix.

Try it

Ship a change through a preview

Use a preview deployment to try a small change before it goes live. Change the home page heading from "My Reading List" to include your name, check it on a preview URL, and then release it to production.

Show solution
git switch -c personal-heading

Edit app/page.tsx:

app/page.tsx
<h1>Sam's Reading List</h1>

Commit and push the branch:

git add app/page.tsx
git commit -m "Personalise the heading"
git push -u origin personal-heading

In the Vercel dashboard (or on GitHub, if you open a pull request), a new deployment appears for the personal-heading branch with its own URL. Open it and check the heading. The production URL still shows the old heading.

When you are happy, merge the branch into main, either with a pull request on GitHub or locally:

git switch main
git merge personal-heading
git push

The push to main triggers a production deployment, and the new heading goes live. If you prefer the CLI, vercel from the branch gives you a preview URL and vercel --prod from main releases it.

Quick check

Where should a database password for your deployed app live?

Day 7 progress

0/8
Next: What's next

On this page