Home Quizzes Leaderboard Competitions Learn Hire Us
About Contact
Log In Sign Up
Learn Next.js Deployment --- Vercel & Environment Variables

Deployment --- Vercel & Environment Variables

⏱ 15 min read read
Deploy to Vercel --- 3 Steps:

1. Push your project to GitHub

2. Go to vercel.com → New Project → Import from GitHub

3. Click Deploy --- Vercel detects Next.js automatically

# Or use the CLI

npm install -g vercel

vercel # deploys to preview URL

vercel --prod # deploys to production

Environment Variables:

.env.local --- local dev only, never committed to git

.env.development --- only in dev (npm run dev)

.env.production --- only in production build

.env --- all environments (safe defaults only)

NEXT_PUBLIC\_ prefix --- exposed to the browser

No prefix --- server-only (secure)

NEXT_PUBLIC_API_URL=https://api.example.com ← browser-safe

DATABASE_URL=postgres://... ← server-only

AUTH_SECRET=abc123 ← server-only

Accessing Env Vars:

// Server only (Route Handlers, Server Components, Server Actions)

process.env.DATABASE_URL

process.env.AUTH_SECRET

// Client + Server (NEXT_PUBLIC\_ prefix)

process.env.NEXT_PUBLIC_API_URL

Vercel Features:

// Edge Runtime --- deploy to 300+ global PoPs

export const runtime = 'edge'; // in any route or route handler

// Cron jobs --- vercel.json

{ "crons": [{ "path": "/api/cron", "schedule": "0 0 * *
*" }] }

// Preview deployments --- automatic for every PR/branch

Always add .env.local to .gitignore --- it contains secrets.

Set production env vars in Vercel dashboard → Settings → Environment
Variables.

Vercel Edge Functions run at the CDN edge --- ultra-low latency
globally.

Other deployment options: Netlify, Railway, Render, Docker + any
cloud VPS.
Code Example
// .env.local (never commit this file!)

DATABASE_URL=postgresql://user:pass@localhost:5432/mydb

AUTH_SECRET=super-secret-random-string

NEXT_PUBLIC_APP_URL=http://localhost:3000

NEXT_PUBLIC_STRIPE_KEY=pk_test\_...

// .env (safe defaults --- can commit)

NEXT_PUBLIC_APP_NAME=MyApp

NEXT_PUBLIC_APP_VERSION=1.0.0

// lib/env.ts --- typed, validated env vars with Zod

import { z } from 'zod';

const envSchema = z.object({

DATABASE_URL: z.string().url(),

AUTH_SECRET: z.string().min(32),

NEXT_PUBLIC_APP_URL: z.string().url(),

});

export const env = envSchema.parse(process.env);

// Throws at startup if any var is missing --- fail fast!

// Usage

import { env } from '@/lib/env';

const db = new PrismaClient({ datasources: { db: { url:
env.DATABASE_URL } } });

// vercel.json --- cron + headers

// {

// "crons": [{ "path": "/api/cron/cleanup", "schedule": "0
2 * * *" }],

// "headers": [{

// "source": "/api/(.*)",

// "headers": [{ "key": "X-Content-Type-Options", "value":
"nosniff" }]

// }]

// }

// app/api/cron/cleanup/route.ts --- runs daily at 2am

export const runtime = 'nodejs';

export async function GET(req: Request) {

const auth = req.headers.get('authorization');

if (auth !== `Bearer ${process.env.CRON_SECRET}`) {

return new Response('Unauthorized', { status: 401 });

}

// await db.sessions.deleteMany({ where: { expiresAt: { lt: new
Date() } } });

return Response.json({ message: 'Cleanup done', time: new
Date().toISOString() });

}
← Internationalisation (i18n) Final Project --- Full-Stack Learning Pl →

Log in to track your progress and earn badges as you complete lessons.

Log In to Track Progress