Deploying Your Project
What Is Deployment?
Your project runs fine locally — type npm run dev, open localhost:3000 in the browser, perfect. But that address is only accessible from your computer. Your friends and users can't see it.
Deployment, simply put, means moving your code from your computer to a public server so anyone in the world can access it via the internet.
Analogy: You cook a great meal at home (local development) — only you can eat it. Deployment means bringing that meal to a restaurant (server), putting up an address (domain), and letting everyone come eat.
Deployment used to be a real pain — you had to buy a server, install an operating system, configure Nginx, set up SSL certificates, handle domain resolution... that alone scared off half the people.
But now, there are tons of "deployment platforms" that handle all of that. You just push your code to GitHub, click a few buttons, and your product is live in minutes. You don't need to know server operations. You really don't.
The flow looks like this:
Your computer → GitHub (code repository) → Deployment platform (auto-build + publish) → Users on the internet
You handle writing and pushing code; the platform handles everything else. Let's look at the specifics.
Vercel: The Best Partner for Next.js
If you're using Next.js (which you probably are), Vercel is your first choice.
Why? Because Vercel was built by the same company that created Next.js. They're family, so the Next.js support is absurdly good — auto-detection, auto-build, auto-deploy. You barely need to configure anything.
Complete Vercel Deployment Process
Step 1: Push Code to GitHub
First, make sure your code is already on GitHub. If not:
# Run in your project root
git init
git add .
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/your-username/your-repo.git
git push -u origin main
If you haven't created a GitHub repo yet, go to github.com, click "+" in the top right → "New repository," create one, then follow the prompts to push your local code.
Step 2: Connect Vercel
- Open vercel.com, click "Sign Up" or "Log In" in the top right
- Choose "Continue with GitHub" — authorize with your GitHub account
- Enter Vercel's Dashboard — you'll see a clean page
- Click the "Add New Project" button
- Vercel will list all your GitHub repos. Find your project and click "Import"
Step 3: Configure the Project
After importing, you'll see a configuration page:
- Framework Preset: Vercel auto-detects your project is Next.js and shows the "Next.js" icon. No manual selection needed.
- Root Directory: Defaults to the project root — only change if your code is in a subdirectory.
- Build and Output Settings: Usually keep defaults — Vercel knows what build command Next.js needs.
- Environment Variables: This is the most important part — covered separately below.
Step 4: Click Deploy
Hit the blue "Deploy" button. You'll see real-time build logs — wait about 1-2 minutes. When the build finishes, Vercel will celebrate with confetti and give you a .vercel.app domain like your-project.vercel.app.
Open it — your product is live!
From now on, every time you push code to the main branch on GitHub, Vercel automatically redeploys. This is called CI/CD (Continuous Integration/Continuous Deployment) — it works out of the box with no extra setup.
Environment Variables
This is where beginners run into the most issues. Read carefully.
Your project might have a .env.local file with sensitive info:
# .env.local
OPENAI_API_KEY=sk-xxx...xxxx
DATABASE_URL=postgresql://user:***@host:5432/db
NEXTAUTH_SECRET=your-secret-here
This file isn't pushed to GitHub (.gitignore excludes it), so Vercel can't read it. You need to manually configure it in Vercel:
- Go to your Vercel project page
- Click the "Settings" tab at the top
- Find "Environment Variables" in the left menu
- Add each one: Key is the variable name (e.g.,
OPENAI_API_KEY), Value is the corresponding value - Environment selection: Check Production, Preview, and Development so it works everywhere
- Click "Save"
# If you want to bulk import via Vercel CLI:
# Install Vercel CLI first
npm i -g vercel
# Pull env vars in project directory
vercel env pull .env.local
# Or add a single variable manually
vercel env add OPENAI_API_KEY
What happens if you forget? The deploy succeeds, but your app will error out everywhere — API calls fail, database won't connect, third-party auth breaks. Remember: working locally doesn't mean working in production. Environment variables are the bridge between the two.
Custom Domains
.vercel.app works, but it's not professional enough. Bind your own domain (e.g., myapp.com):
- Buy a domain from a registrar (Cloudflare, Namecheap, etc.)
- In Vercel project settings, click "Domains"
- Enter your domain, click "Add"
- Vercel will tell you what DNS records to configure — typically:
- A
CNAMErecord pointing tocname.vercel-dns.com - Or an
Arecord pointing to Vercel's IP
- A
- Add these DNS records at your domain registrar
- Wait a few minutes to a few hours for DNS propagation, and your domain will work
SSL certificates? Vercel automatically requests and renews them. https works out of the box.
The free plan supports multiple custom domains at no extra cost.
Serverless Functions
Vercel's Serverless Functions are how your backend APIs run.
Simple explanation: Traditional backend servers run continuously, consuming resources even when nobody's visiting. Serverless Functions are different — they only start when someone makes a request, and go to sleep when nobody does. No server management, no scaling worries, pay-per-use (free tier is enough for personal projects).
In a Next.js project, your API Routes are Serverless Functions:
// app/api/hello/route.ts
export async function GET() {
return Response.json({ message: "Hello from serverless!" });
}
export async function POST(request: Request) {
const body = await request.json();
// Process business logic...
return Response.json({ success: true, data: body });
}
Things to note:
- Free plan limits each execution to 10 seconds — if your endpoint calls a slow external API (like AI generation), it might time out
- Cold start: If a function hasn't been called in a while, the first request may be a few hundred milliseconds to a couple seconds slower
- Functions can't store state (they might be destroyed at any time) — persistent data goes in the database
vercel.json Configuration
Create vercel.json in the project root to customize deployment behavior:
{
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Access-Control-Allow-Origin", "value": "*" },
{ "key": "Access-Control-Allow-Methods", "value": "GET,POST,PUT,DELETE" }
]
}
],
"redirects": [
{
"source": "/old-page",
"destination": "/new-page",
"permanent": true
}
],
"rewrites": [
{
"source": "/blog/:slug",
"destination": "/api/blog/:slug"
}
]
}
Common use cases:
{
"functions": {
"app/api/ai-generate/route.ts": {
"maxDuration": 30
}
}
}
This extends the timeout for a specific API route from 10 to 30 seconds (requires Pro plan to exceed the 10-second limit).
{
"regions": ["hkg1", "sin1"]
}
Specify which regions to deploy functions to — hkg1 is Hong Kong, sin1 is Singapore. Closer to your users means faster responses.
Vercel Free Tier
Hobby plan (free) limits — good to know:
| Resource | Limit |
|---|---|
| Bandwidth | 100GB/month |
| Builds | 100/month |
| Serverless Function execution | 100GB-hours/month |
| Single function execution time | Max 10 seconds |
| Projects | Unlimited |
| Custom domains | Unlimited |
| Team collaboration | Personal only |
What does 100GB of bandwidth mean? If your pages average 500KB, 100GB supports roughly 200,000 page views. More than enough for personal projects. Consider upgrading to Pro ($20/month) when you're making thousands per month.
Cloudflare Pages: Another Great Option
Cloudflare Pages is a frontend deployment platform from Cloudflare, similar to Vercel but with its own set of advantages.
Comparison with Vercel
| Feature | Vercel | Cloudflare Pages |
|---|---|---|
| Free bandwidth | 100GB/month | Unlimited |
| Free builds | 100/month | 500/month |
| Global nodes | Many | More (300+ cities) |
| Next.js support | Perfect (first-party) | Good, but some advanced features have quirks |
| Learning curve | Low | Medium |
| Serverless | Yes | Yes (Cloudflare Workers) |
| Free database | No | Yes (D1) |
When to Choose Cloudflare?
- High traffic, concerned about Vercel's 100GB bandwidth limit
- Users mainly in China (Cloudflare has China nodes, but requires an ICP-registered domain)
- Want to use Cloudflare's other products (Workers, D1 database, R2 object storage, etc.)
- Project is a static site or simple full-stack app
Basic Deployment Steps
- Open dash.cloudflare.com, log in or register
- Find "Workers & Pages" in the left menu
- Click "Create" → "Pages" → "Connect to Git"
- Authorize GitHub, select your repo
- Configure build settings:
- Framework preset: "Next.js"
- Build command:
npm run build(usually auto-filled) - Build output directory: usually auto-filled
- Add environment variables (similar to Vercel)
- Click "Save and Deploy"
After deployment, you'll get a *.pages.dev domain.
Heads up: If your Next.js project uses advanced App Router features (like revalidatePath, unstable_cache, etc.), you might hit compatibility issues on Cloudflare Pages. Deploy a test first — if there are problems, adjust accordingly.
Other Deployment Platforms
Netlify
Netlify is a veteran frontend deployment platform — it predates Vercel. The workflow is similar — connect GitHub repo, auto-build, auto-deploy. The free plan offers 100GB bandwidth and 300 build minutes per month. Netlify's strength is its mature ecosystem with built-in solutions for form handling, authentication, A/B testing, and more. Great for pure static sites or projects using Netlify-specific features (like Netlify Functions). However, for Next.js projects, Vercel's support is still better.
Railway
Railway isn't just for frontend — it's more like a lightweight cloud server platform. You can deploy databases (PostgreSQL, MySQL, Redis), backend services, cron jobs, and more. It supports Docker and can deploy directly from GitHub. The free plan includes $5/month — roughly enough for a small database and a lightweight backend. If your project needs a real backend server beyond Serverless Functions, Railway offers excellent value. The interface is modern and pleasant to use.
Fly.io
Fly.io is a platform that "deploys your app closest to your users." It has nodes in cities worldwide, and your app gets deployed to multiple geographic locations. It supports Docker container deployment, making it ideal for long-running backend services (like WebSocket servers, game servers). The free plan includes 3 shared CPU VMs and some memory/storage. Fly.io has a steeper learning curve than Vercel or Railway — it requires some Docker and networking knowledge, making it better suited for advanced users.
Top 5 Deployment Issues
1. Missing Environment Variables
Symptoms: Works locally, but production shows undefined everywhere, 500 errors, database won't connect.
Fix: Check Vercel Settings > Environment Variables. Make sure all .env.local variables are configured. After configuring, you need to redeploy for changes to take effect (trigger a new deployment or click Redeploy in the Vercel dashboard).
2. Build Failure
Symptoms: Vercel logs show a red Error — deployment fails completely.
Fix: Read the error message carefully. Common causes:
- TypeScript type errors: local
devmode may skip type checking, butbuildchecks strictly - Missing dependencies: verify
package.jsonincludes all required packages - Package incompatible with Node.js: for browser-only packages, wrap with
typeof window !== 'undefined'
Run npm run build locally first. If local build also fails, fix it before pushing.
3. API Route Timeout
Symptoms: API calls return 504 Gateway Timeout.
Fix: Vercel free plan limits Serverless Functions to 10 seconds per execution. Solutions:
- Reduce external API calls
- Add caching to avoid duplicate requests
- Use streaming responses instead of returning everything at once
- If you genuinely need more time, upgrade to Pro (up to 60 seconds)
4. 404 Errors
Symptoms: Certain pages return 404 Not Found.
Fix: Check that your file structure follows Next.js routing conventions. In App Router:
app/
page.tsx → Homepage /
about/
page.tsx → /about
blog/
[slug]/
page.tsx → /blog/xxx (dynamic route)
Note: it's page.tsx, not index.tsx. It's layout.tsx, not _app.tsx.
5. Image Loading Failures
Symptoms: Images don't display, console shows Invalid src prop errors.
Fix: Next.js's next/image component requires you to configure allowed image domains in next.config.js:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.unsplash.com',
},
{
protocol: 'https',
hostname: '*.amazonaws.com',
},
],
},
};
module.exports = nextConfig;
Redeploy after configuring.
Build Errors vs Runtime Errors
Understanding these two concepts makes debugging much faster.
Build Error: Happens during "construction." Vercel reads your code, compiles, and bundles — something goes wrong. Your app never goes live.
- Symptoms: Red error in Vercel build logs, deployment status is "Error"
- Common causes: Syntax errors, TypeScript type errors, dependency issues
- How to debug: Check Vercel's build logs — the error tells you exactly which file and line
- How to fix: Run
npm run buildlocally to reproduce, fix, then push
Runtime Error: Happens "after moving in." The app is live, but users encounter problems while using it.
- Symptoms: App is accessible but certain operations fail (white screen, 500 errors, broken features)
- Common causes: Missing environment variables, failed API calls, null pointers, wrong data formats
- How to debug: Check browser Console (F12), Vercel Functions logs, user reports
- How to fix: Fix code or configuration based on the specific error
Simple rule of thumb: Build error = code is wrong, won't compile. Runtime error = compiled fine, but breaks during use.
Preview Deployments
This is an incredibly useful feature that many people don't know about.
What are Preview Deployments? When you create a Pull Request (PR) instead of pushing directly to main, Vercel automatically deploys a preview version for that PR with its own URL.
For example, if you push a PR to the feature/new-homepage branch, Vercel deploys something like your-project-abc123.vercel.app. You'll see this link in the PR comments.
Why is this useful?
- Preview before going live: No need to open two browsers locally — just open the preview link to see changes
- Team collaboration: Designers and PMs can click the link to see your changes without understanding code
- Doesn't affect production: Preview deployments are isolated — breaking changes don't impact live users
- Auto-cleanup: When the PR is merged or closed, the preview deployment is automatically cleaned up
How to use? No extra configuration needed — Vercel enables this by default. Just push code to a new branch and create a PR on GitHub.
# Create new branch
git checkout -b feature/add-dark-mode
# Write code, commit
git add .
git commit -m "add dark mode toggle"
git push origin feature/add-dark-mode
# Then go to GitHub and create a Pull Request
# Vercel automatically comments a preview link in the PR
Post-Deployment Monitoring
Your product is live — but how do you know if it's down? You need some basic monitoring.
Free Monitoring Tool Recommendations
UptimeRobot (uptimerobot.com)
- Free plan monitors 50 URLs
- Checks every 5 minutes if your site is accessible
- Sends email/SMS alerts when it goes down
- Super easy setup: Add your URL → set monitoring interval → add alert email, done
Better Stack (betterstack.com)
- Free plan monitors 5 URLs, checks every 3 minutes
- Better-looking interface, richer features
- Beyond HTTP monitoring, can monitor ports, keywords, and more
- Has a Status Page to show users your system status
Google Search Console (search.google.com/search-console)
- Not a traditional monitoring tool, but important for SEO
- Submit your site and Google tells you about page crawl errors
- Also shows your site's performance in Google Search
Basic Monitoring Setup
Using UptimeRobot as an example — 3 minutes to set up:
- Create an account (Google login supported)
- Click "Add New Monitor"
- Monitor Type: "HTTP(s)"
- Friendly Name: your project name
- URL: your site address (e.g.,
https://your-project.vercel.app) - Monitoring Interval: 5 minutes
- Alert Contacts: your email
- Click "Create Monitor"
Done! If your site goes down, you'll get an email within 5 minutes.
Vercel's Built-in Analytics
Vercel's Analytics feature shows you:
- How many visitors per day
- Which pages are most popular
- Page load speed
- Core Web Vitals (Google's performance metrics)
The free plan includes basic Web Analytics; Pro has more detailed data. Enable it in project settings under the "Analytics" tab.
What to Do After Deployment
Going live isn't the finish line — it's the starting line.
Use it yourself end-to-end. Register, log in, test core features, try edge cases. Many bugs only appear in real network environments — using localhost vs a real domain is a completely different experience.
Have friends try it. Find 3-5 willing friends, let them use it freely, and record the problems and confusion they encounter. You'll find that things you take for granted may be completely unclear to them.
Look at the data. Even simple visit counts tell you a lot. Are people coming? What features do they use? Where do they drop off? This data guides your next decisions.
Keep iterating. Based on user feedback and data, continuously improve. Deployment platforms make "releasing a new version" incredibly simple — just push code. Leverage this advantage to fail fast and iterate quickly.
The moment your product goes live, you'll feel a real sense of accomplishment. Enjoy it — then get back to work.