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