Deployment Guide - dinesh-git17/my-progress-planner GitHub Wiki

Complete guide for deploying My Progress Planner to production.

🚀 Deployment Options

1. Vercel (Recommended)

Vercel provides the best experience for Next.js applications with automatic deployments, edge functions, and global CDN.

Quick Deploy

Deploy with Vercel

Manual Vercel Setup

  1. Install Vercel CLI

    npm install -g vercel
    
  2. Login to Vercel

    vercel login
    
  3. Deploy from project directory

    vercel --prod
    
  4. Configure environment variables in Vercel dashboard

Vercel Configuration (vercel.json)

{
  "crons": [
    {
      "path": "/api/cron/lunch",
      "schedule": "0 18 * * *"
    },
    {
      "path": "/api/cron/dinner", 
      "schedule": "0 1 * * *"
    }
  ],
  "functions": {
    "src/app/api/admin/*/route.ts": {
      "maxDuration": 30
    },
    "src/app/api/ai/*/route.ts": {
      "maxDuration": 25
    }
  },
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "no-store, no-cache, must-revalidate"
        }
      ]
    }
  ]
}

2. Netlify

Alternative deployment option with similar features.

  1. Connect GitHub repository to Netlify
  2. Build settings:
    • Build command: npm run build
    • Publish directory: .next
  3. Environment variables - Add in Netlify dashboard
  4. Deploy - Automatic on git push

3. Railway

Simple deployment with built-in database options.

  1. Install Railway CLI

    npm install -g @railway/cli
    
  2. Login and deploy

    railway login
    railway init
    railway up
    
  3. Add environment variables

    railway variables set OPENAI_API_KEY=sk-...
    

4. Self-Hosted (Docker)

For full control over your deployment.

Dockerfile

FROM node:18-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production

FROM node:18-alpine AS builder
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
RUN npm run build

FROM node:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV production

RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

USER nextjs
EXPOSE 3000
ENV PORT 3000

CMD ["node", "server.js"]

Docker Compose

version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL}
      - NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
      - SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_KEY}
      - OPENAI_API_KEY=${OPENAI_API_KEY}
    restart: unless-stopped

⚙️ Environment Configuration

Required Environment Variables

Create .env.production file:

# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# OpenAI Integration
OPENAI_API_KEY=sk-proj-...

# Security
CRON_SECRET=your-secure-random-string-32-chars
ADMIN_PASSWORD=YourSecureAdminPassword2025!

# Domain Configuration
NEXT_PUBLIC_SITE_URL=https://your-domain.com

# Optional: Push Notifications
VAPID_PUBLIC_KEY=BDd3_hVL9fNUoHogP7s2WjA...
VAPID_PRIVATE_KEY=bdSiGDWlj4AA5BdyQRAr...
PUSH_CONTACT_EMAIL=mailto:[email protected]

Vercel Environment Variables Setup

  1. Go to Vercel Dashboard → Your Project → Settings → Environment Variables

  2. Add each variable:

    • NEXT_PUBLIC_SUPABASE_URL - Production, Preview, Development
    • NEXT_PUBLIC_SUPABASE_ANON_KEY - Production, Preview, Development
    • SUPABASE_SERVICE_ROLE_KEY - Production, Preview, Development
    • OPENAI_API_KEY - Production, Preview, Development
    • CRON_SECRET - Production, Preview
    • ADMIN_PASSWORD - Production only
  3. Redeploy to apply changes

🏗️ Build Configuration

Next.js Configuration (next.config.mjs)

/** @type {import('next').NextConfig} */
const nextConfig = {
  // Enable static optimization
  output: 'standalone',
  
  // PWA configuration
  experimental: {
    webpackBuildWorker: true,
  },
  
  // Security headers
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'X-Frame-Options',
            value: 'DENY',
          },
          {
            key: 'X-Content-Type-Options',
            value: 'nosniff',
          },
          {
            key: 'Referrer-Policy',
            value: 'origin-when-cross-origin',
          },
        ],
      },
    ];
  },
  
  // Environment variables validation
  env: {
    CUSTOM_KEY: process.env.CUSTOM_KEY,
  },
  
  // Image optimization
  images: {
    domains: ['your-domain.com'],
    formats: ['image/webp', 'image/avif'],
  },
};

export default nextConfig;

🔒 SSL/TLS Setup

Custom Domain with SSL

  1. Domain Setup

    • Point your domain to deployment platform
    • Add CNAME record: www.your-domain.comyour-app.vercel.app
  2. SSL Certificate

    • Vercel: Automatic Let's Encrypt certificates
    • Netlify: Automatic SSL with custom domains
    • Self-hosted: Use Certbot for Let's Encrypt

SSL Configuration for Self-Hosted

# Install Certbot
sudo apt install certbot python3-certbot-nginx

# Generate certificate
sudo certbot --nginx -d your-domain.com -d www.your-domain.com

# Auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet

📊 Performance Optimization

Build Optimization

# Analyze bundle size
npm run build
npx @next/bundle-analyzer

# Check for unused dependencies
npx depcheck

# Optimize images
npm install sharp

Caching Strategy

// next.config.mjs - Cache headers
async headers() {
  return [
    {
      source: '/api/ai/quote',
      headers: [
        {
          key: 'Cache-Control',
          value: 'public, s-maxage=3600, stale-while-revalidate=86400',
        },
      ],
    },
    {
      source: '/(.*).png',
      headers: [
        {
          key: 'Cache-Control', 
          value: 'public, max-age=31536000, immutable',
        },
      ],
    },
  ];
},

CDN Configuration

For Vercel, CDN is automatic. For self-hosted:

# Nginx configuration
server {
    listen 443 ssl http2;
    server_name your-domain.com;
    
    # Gzip compression
    gzip on;
    gzip_types text/css application/javascript image/svg+xml;
    
    # Static file caching
    location ~* \.(js|css|png|jpg|jpeg|gif|svg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # API routes - no cache
    location /api/ {
        add_header Cache-Control "no-store, no-cache, must-revalidate";
        proxy_pass http://localhost:3000;
    }
    
    # All other routes
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

🔄 CI/CD Pipeline

GitHub Actions Workflow

# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - run: npm ci
      - run: npm run type-check
      - run: npm run lint
      - run: npm run test
      - run: npm run build

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'
      
      - run: npm ci
      - run: npm run build
      
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'

🗄️ Database Deployment

Supabase Production Setup

  1. Create Production Project

    • New project in Supabase dashboard
    • Choose closest region to users
    • Select appropriate pricing plan
  2. Database Migration

    # Install Supabase CLI
    npm install -g supabase
    
    # Login
    supabase login
    
    # Link to project
    supabase link --project-ref your-project-id
    
    # Push schema
    supabase db push
    
  3. Row Level Security

    -- Enable RLS on all tables
    ALTER TABLE users ENABLE ROW LEVEL SECURITY;
    ALTER TABLE meals ENABLE ROW LEVEL SECURITY;
    ALTER TABLE summaries ENABLE ROW LEVEL SECURITY;
    ALTER TABLE friends ENABLE ROW LEVEL SECURITY;
    ALTER TABLE push_subscriptions ENABLE ROW LEVEL SECURITY;
    

Database Backup Strategy

# Automated daily backups
pg_dump "postgresql://user:pass@host:port/db" > backup-$(date +%Y%m%d).sql

# Backup to cloud storage
aws s3 cp backup-$(date +%Y%m%d).sql s3://your-backup-bucket/

📈 Monitoring Setup

Error Tracking

Add error tracking service:

// lib/error-tracking.ts
import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NODE_ENV,
});

export { Sentry };

Performance Monitoring

// lib/analytics.ts
export function trackPageView(url: string) {
  if (process.env.NODE_ENV === 'production') {
    // Google Analytics, Plausible, etc.
    gtag('config', 'GA_MEASUREMENT_ID', {
      page_path: url,
    });
  }
}

Health Checks

// app/api/health/route.ts
import { NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase-server';

export async function GET() {
  try {
    const supabase = createClient();
    const { error } = await supabase.from('users').select('count').limit(1);
    
    if (error) throw error;
    
    return NextResponse.json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      services: {
        database: 'connected',
        openai: process.env.OPENAI_API_KEY ? 'configured' : 'missing'
      }
    });
  } catch (error) {
    return NextResponse.json(
      { status: 'unhealthy', error: error.message },
      { status: 500 }
    );
  }
}

🔐 Security Checklist

Pre-Deployment Security

  • Environment variables secured
  • API keys rotated for production
  • Database RLS policies enabled
  • HTTPS enforced
  • Security headers configured
  • Input validation on all endpoints
  • Rate limiting implemented
  • CORS configured properly
  • Dependencies audited (npm audit)
  • Secrets not in git history

Post-Deployment Security

# Security audit
npm audit --audit-level moderate

# Check for vulnerabilities
npx audit-ci --moderate

# SSL/TLS test
curl -I https://your-domain.com

# Security headers test
curl -I https://your-domain.com | grep -E "(X-Frame|X-Content|Strict-Transport)"

📋 Deployment Checklist

Pre-Deployment

  • All tests passing
  • Environment variables configured
  • Database schema updated
  • Build successful locally
  • Dependencies up to date
  • Performance benchmarks met

Deployment

  • Deploy to staging first
  • Run smoke tests
  • Verify all features work
  • Check monitoring/alerting
  • Deploy to production
  • Verify production functionality

Post-Deployment

  • Monitor error rates
  • Check performance metrics
  • Verify cron jobs working
  • Test push notifications
  • Update documentation
  • Notify team of deployment

🚨 Rollback Plan

Quick Rollback

# Vercel rollback
vercel rollback

# Or redeploy previous commit
git revert HEAD
git push origin main

Database Rollback

# Restore from backup
pg_restore -d production_db backup-20250101.sql

# Or run migration rollback
supabase migration down

📞 Support