Deploying a React App to Vercel — The Right Way
A complete, no-fluff guide to deploying a React application on Vercel — from the first commit all the way to custom domains, environment variables, and preview deployments.
May 28, 2026
Vercel is the easiest way to ship a React app. But there are a few things worth understanding properly — environment variables, preview deployments, custom domains — so that your setup is solid from day one, not something you patch later.
This is the guide I wish I had when I started.
Prerequisites
- A React app (Vite, Create React App, or Next.js)
- A GitHub account with your code pushed to a repository
- A free Vercel account — sign up at vercel.com with GitHub
Step 1 — Prepare Your Project
Before you deploy, make sure your project builds without errors locally:
# For Vite
npm run build
# For Create React App
npm run build
# For Next.js
npm run build
Fix any type errors or missing dependency warnings now — Vercel runs the exact same build command in a clean environment.
Check your .gitignore
Your .gitignore must exclude build outputs and local secrets. At minimum:
node_modules/
dist/
.next/
.env
.env.local
.env*.local
Commit these files if you haven't:
git add .gitignore
git commit -m "chore: add gitignore"
git push
Step 2 — Import Your Project on Vercel
- Go to vercel.com/new
- Click "Import Git Repository" and select your repo
- Vercel will auto-detect your framework and set the correct build command:
- Vite:
vite build→ output:dist/ - CRA:
react-scripts build→ output:build/ - Next.js:
next build→ output:.next/
- Vite:
You usually don't need to change anything here. Click Deploy.
Within 30–60 seconds your app is live on a .vercel.app URL.
Step 3 — Environment Variables
Never commit secrets to Git. If your app hits an API, you need environment variables.
Adding them on Vercel
- Open your project dashboard on Vercel
- Go to Settings → Environment Variables
- Add your variables:
VITE_API_URL=https://api.yourdomain.com
VITE_IMAGEKIT_PUBLIC_KEY=public_...
Important for Vite: variables must be prefixed with
VITE_to be exposed to the browser bundle. For Create React App the prefix isREACT_APP_. Next.js usesNEXT_PUBLIC_for client-side variables.
Environment scopes
Vercel lets you set variables per environment:
| Scope | When it applies |
|---|---|
| Production | Deployed from your main/master branch |
| Preview | Every pull request deployment |
| Development | When you run vercel dev locally |
This means you can point preview deployments at a staging API and production at your real one — without changing any code.
Step 4 — Preview Deployments (The Killer Feature)
Every time you open a pull request on GitHub, Vercel automatically builds it and gives it a unique URL like:
https://my-app-git-feature-branch-username.vercel.app
This means:
- You can share a working preview link with a collaborator before merging
- You can catch bugs that only appear after building (not just in dev)
- No staging server to maintain
To test this, create a branch, push a change, and open a PR on GitHub. Vercel will post a comment on the PR with the preview URL automatically.
Step 5 — Custom Domain
- Go to Settings → Domains in your Vercel project
- Add your domain, e.g.
blog.ariyaman.dev - Vercel gives you DNS records to add at your registrar (usually an
Arecord orCNAME) - Once DNS propagates (usually under 5 minutes with Cloudflare), your domain is live with HTTPS — fully managed, no certificate setup needed
Step 6 — Automatic Deploys on Push
Once set up, your workflow is:
git add .
git commit -m "feat: new blog post"
git push origin main
Vercel detects the push, runs your build, and deploys the new version. The entire process takes under a minute. Your old deployment stays live until the new one passes — so there's zero downtime.
Common Gotchas
Client-side routing 404s
If you're using React Router and a user navigates directly to /blog/post-1, Vercel needs to know to serve index.html instead of returning a 404.
Create a vercel.json file at the project root:
{
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
]
}
This is only needed for Vite/CRA SPAs. Next.js handles this automatically.
Build succeeds locally but fails on Vercel
This almost always means:
- A dependency is in
devDependencieswhen it should be independencies - A case-sensitivity issue (Linux on Vercel is case-sensitive, macOS is not)
- An environment variable is missing in the Vercel dashboard
Check the build logs in the Vercel dashboard — they show the exact error with a stack trace.
Large bundle sizes
Vercel will warn you if your bundle is unusually large. Common culprits are importing an entire library when you only need one function:
// ❌ Imports the entire lodash library
import _ from 'lodash';
// ✅ Import only what you need
import debounce from 'lodash/debounce';
Summary
Vercel makes deployment genuinely easy — import your repo, add your env vars, push to main. That's the core loop.
The things that separate a well-configured deployment from a rough one are:
- Environment variables scoped correctly per environment
vercel.jsonfor SPA routing rewrites- Preview deployments wired up to your PR workflow
Once it's set up, deploying feels like just running git push.