Intermediate15 min1 prerequisite

Deploy your Next.js application to Vercel and other platforms with production-ready configuration.

Deployment & Production

Getting your AI-built Next.js application into production requires understanding deployment options, environment configuration, and performance optimization.

Deployment Options

Vercel (Recommended)

The creators of Next.js—seamless integration:

Terminal
# Install Vercel CLI
npm install -g vercel

# Deploy from project root
vercel

# Deploy to production
vercel --prod

Or connect via GitHub:

  1. Push to GitHub
  2. Visit vercel.com
  3. Import repository
  4. Automatic deploys on push

Netlify

Supports Next.js with some limitations:

Terminal
# Install Netlify CLI
npm install -g netlify-cli

# Deploy
netlify deploy --prod

Self-Hosted (Node.js)

Build and run on your own server:

Terminal
# Build
npm run build

# Start production server
npm start

Docker deployment:

Terminal
FROM node:20-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

ENV NODE_ENV=production
EXPOSE 3000
CMD ["npm", "start"]

Static Export

For static hosting (GitHub Pages, S3):

Terminal
// next.config.js
const nextConfig = {
  output: 'export',
}

module.exports = nextConfig
Terminal
npm run build
# Output in 'out' directory

Limitations:

  • No Server Components (become static)
  • No API routes
  • No ISR/revalidation
  • No image optimization

Environment Variables

Types of Variables

Terminal
.env                  # All environments
.env.local            # Local overrides (gitignored)
.env.development      # Development only
.env.production       # Production only

Server vs Client Variables

Terminal
# .env.local

# Server-side only (secure)
DATABASE_URL="postgresql://..."
API_SECRET="secret-key"

# Exposed to browser (public)
NEXT_PUBLIC_API_URL="https://api.example.com"
NEXT_PUBLIC_STRIPE_KEY="pk_live_..."

In code:

Terminal
// Server Component - access all variables
const dbUrl = process.env.DATABASE_URL

// Client Component - only NEXT_PUBLIC_*
const apiUrl = process.env.NEXT_PUBLIC_API_URL

Vercel Environment Variables

  1. Go to Project Settings → Environment Variables
  2. Add variables with scope:
    • Production
    • Preview
    • Development

Validation

Terminal
// lib/env.ts
import { z } from 'zod'

const envSchema = z.object({
  DATABASE_URL: z.string().url(),
  NEXTAUTH_SECRET: z.string().min(32),
  NEXT_PUBLIC_API_URL: z.string().url(),
})

export const env = envSchema.parse({
  DATABASE_URL: process.env.DATABASE_URL,
  NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
  NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
})

Build Configuration

next.config.js

Terminal
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Output type
  output: 'standalone', // For Docker

  // Image domains
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.example.com',
      },
    ],
  },

  // Redirects
  async redirects() {
    return [
      {
        source: '/old-page',
        destination: '/new-page',
        permanent: true,
      },
    ]
  },

  // Rewrites (proxy)
  async rewrites() {
    return [
      {
        source: '/api/:path*',
        destination: 'https://api.example.com/:path*',
      },
    ]
  },

  // Headers
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'X-Frame-Options',
            value: 'DENY',
          },
        ],
      },
    ]
  },
}

module.exports = nextConfig

TypeScript Strict Mode

Terminal
// tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true
  }
}

Performance Optimization

Image Optimization

Terminal
import Image from 'next/image'

// Optimized automatically
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority // Load immediately (LCP)
/>

// Remote images
<Image
  src="https://external.com/image.jpg"
  alt="External"
  width={400}
  height={300}
/>

Font Optimization

Terminal
// app/layout.tsx
import { Inter } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}

Code Splitting

Automatic with dynamic imports:

Terminal
import dynamic from 'next/dynamic'

// Load component only when needed
const HeavyChart = dynamic(() => import('./HeavyChart'), {
  loading: () => <p>Loading chart...</p>,
  ssr: false, // Client-side only
})

Bundle Analysis

Terminal
# Install analyzer
npm install @next/bundle-analyzer

# next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})

module.exports = withBundleAnalyzer(nextConfig)

# Run analysis
ANALYZE=true npm run build

Database Connections

Connection Pooling

For serverless environments:

Terminal
// lib/db.ts
import { PrismaClient } from '@prisma/client'

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined
}

export const prisma = globalForPrisma.prisma ?? new PrismaClient()

if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.prisma = prisma
}

Serverless Database Services

  • Vercel Postgres: Native integration
  • PlanetScale: MySQL-compatible, serverless
  • Neon: Serverless Postgres
  • Supabase: Postgres with extras

Monitoring & Analytics

Vercel Analytics

Terminal
npm install @vercel/analytics
Terminal
// app/layout.tsx
import { Analytics } from '@vercel/analytics/react'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Analytics />
      </body>
    </html>
  )
}

Speed Insights

Terminal
npm install @vercel/speed-insights
Terminal
import { SpeedInsights } from '@vercel/speed-insights/next'

// In layout.tsx
<SpeedInsights />

Error Monitoring

Sentry integration:

Terminal
npx @sentry/wizard@latest -i nextjs

Security Checklist

Before Going Live

Terminal
□ Environment variables secured
□ API routes protected
□ CORS configured
□ Rate limiting in place
□ Input validation on all forms
□ SQL injection prevented (use ORM)
□ XSS prevention (React handles most)
□ CSRF tokens for mutations
□ Secure cookies (httpOnly, secure)
□ Content Security Policy headers

Security Headers

Terminal
// next.config.js
async headers() {
  return [
    {
      source: '/(.*)',
      headers: [
        {
          key: 'X-Content-Type-Options',
          value: 'nosniff',
        },
        {
          key: 'X-Frame-Options',
          value: 'DENY',
        },
        {
          key: 'X-XSS-Protection',
          value: '1; mode=block',
        },
        {
          key: 'Referrer-Policy',
          value: 'strict-origin-when-cross-origin',
        },
      ],
    },
  ]
}

Deployment Workflow

Git-Based Deployment

Terminal
1. Push to main → Deploy to production
2. Push to feature branch → Deploy preview
3. Pull request → Preview URL for review

Preview Deployments

Every PR gets a unique URL:

Terminal
https://my-app-abc123.vercel.app

Rollback

Terminal
# Via Vercel CLI
vercel rollback

# Or via dashboard
Deployments → Previous → "..." → Promote to Production

AI Tool Deployment Integration

Lovable/Bolt Deployment

These tools often provide one-click deployment:

  1. Connect GitHub repository
  2. Link Vercel account
  3. Click "Deploy"

Claude Code Deployment

Terminal
You: Deploy this app to Vercel

Claude Code:
├── Checks vercel.json configuration
├── Validates environment variables
├── Runs: vercel --prod
└── Reports deployment URL

Common Deployment Issues

Terminal
Issue: Build fails
→ Check for TypeScript errors
→ Verify all environment variables set
→ Check next.config.js for issues

Issue: API routes 404
→ Verify route.ts file structure
→ Check for export mistakes
→ Confirm dynamic routes syntax

Issue: Images not loading
→ Add domains to next.config.js
→ Check image path/URL
→ Verify image file exists

Summary

  • Vercel: Best for Next.js, zero config
  • Environment variables: Use NEXT_PUBLIC_ for client-side
  • Optimization: Images, fonts, dynamic imports
  • Database: Use connection pooling for serverless
  • Monitoring: Analytics, Speed Insights, error tracking
  • Security: Headers, validation, protected routes

Module Complete

You now understand the Next.js essentials for AI development:

  1. ✅ Introduction to Next.js
  2. ✅ App Router & File Structure
  3. ✅ Server vs Client Components
  4. ✅ Data Fetching Patterns
  5. ✅ Deployment & Production

Continue with Tailwind CSS to learn the styling system that pairs with Next.js in most AI-generated applications.

Mark this lesson as complete to track your progress