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
Manual Vercel Setup
-
Install Vercel CLI
npm install -g vercel
-
Login to Vercel
vercel login
-
Deploy from project directory
vercel --prod
-
Configure environment variables in Vercel dashboard
vercel.json
)
Vercel Configuration ({
"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.
- Connect GitHub repository to Netlify
- Build settings:
- Build command:
npm run build
- Publish directory:
.next
- Build command:
- Environment variables - Add in Netlify dashboard
- Deploy - Automatic on git push
3. Railway
Simple deployment with built-in database options.
-
Install Railway CLI
npm install -g @railway/cli
-
Login and deploy
railway login railway init railway up
-
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
-
Go to Vercel Dashboard → Your Project → Settings → Environment Variables
-
Add each variable:
NEXT_PUBLIC_SUPABASE_URL
- Production, Preview, DevelopmentNEXT_PUBLIC_SUPABASE_ANON_KEY
- Production, Preview, DevelopmentSUPABASE_SERVICE_ROLE_KEY
- Production, Preview, DevelopmentOPENAI_API_KEY
- Production, Preview, DevelopmentCRON_SECRET
- Production, PreviewADMIN_PASSWORD
- Production only
-
Redeploy to apply changes
🏗️ Build Configuration
next.config.mjs
)
Next.js Configuration (/** @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
-
Domain Setup
- Point your domain to deployment platform
- Add CNAME record:
www.your-domain.com
→your-app.vercel.app
-
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
-
Create Production Project
- New project in Supabase dashboard
- Choose closest region to users
- Select appropriate pricing plan
-
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
-
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
- Deployment Issues: Open an issue
- Platform Help: Check specific platform documentation
- Emergency:
[email protected]