Skip to main content
CharleOS is hosted on Vercel, which provides seamless deployment for Next.js applications. This page covers Vercel-specific configuration.

Vercel Setup

Project Configuration

Team: Charle Agency
Project: charle-os
Framework: Next.js 16
Build Command: npm run build
Output Directory: .next

Git Integration

Vercel is connected to the GitHub repository: Repository: charle/charle-os
Production Branch: main
Deploy Previews: All branches
Automatic deployments:
  • ✅ Push to main → Production deployment
  • ✅ Open PR → Preview deployment
  • ✅ Update PR → Preview update
  • ✅ Merge PR → Production deployment

Environment Variables

Setting Environment Variables

  1. Go to Vercel Dashboard
  2. Settings → Environment Variables
  3. Add variable:
    • Name: DATABASE_URL
    • Value: postgresql://...
    • Environments: Production, Preview, Development
  4. Click “Save”

Environment Scopes

Variables can be scoped to specific environments:
ScopeWhen Used
Productionmain branch deployments
PreviewPR/branch preview deployments
DevelopmentLocal development (via vercel dev)
Never use production credentials in preview deployments. Always use separate DEV database and test API keys.

Required Variables

Core

DATABASE_URL=postgresql://...
BETTER_AUTH_SECRET=your-32-char-secret
BETTER_AUTH_URL=https://charle.agency
NEXT_PUBLIC_BETTER_AUTH_URL=https://charle.agency
NEXT_PUBLIC_APP_URL=https://charle.agency
NEXT_PUBLIC_CLIENT_PORTAL_URL=https://clients.charle.agency
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret

Integrations

CLOUDFLARE_WORKER_URL=https://r2-api.charle.agency
R2_UPLOAD_SECRET=your-secret
CLOUDFLARE_R2_PUBLIC_URL=https://files.charle.agency
NEXT_PUBLIC_PUSHER_KEY=your-key
NEXT_PUBLIC_PUSHER_CLUSTER=eu
PUSHER_APP_ID=your-app-id
PUSHER_SECRET=your-secret
RESEND_API_KEY=re_your_key
ALGOLIA_APP_ID=your-app-id
ALGOLIA_ADMIN_API_KEY=your-admin-key
ALGOLIA_SEARCH_API_KEY=your-search-key
SENTRY_AUTH_TOKEN=your-token

Deployment Configuration

Build Settings

// vercel.json (optional - most settings in dashboard)
{
  "buildCommand": "npm run build",
  "devCommand": "npm run dev",
  "framework": "nextjs",
  "installCommand": "npm install"
}

Regions

CharleOS is deployed to:
  • Primary: London (lhr1) - Closest to users
  • Edge: Global CDN for static assets

Build Output

After successful build:
  • .next/ - Built application
  • public/ - Static assets
  • drizzle/ - Migrations (applied during build)

Deployment Workflow

Production Deployment

Developer pushes to main

Vercel webhook triggered

Build starts
  ├── Install dependencies (npm install)
  ├── Run migrations (postinstall hook)
  ├── Build app (next build)
  └── Upload to CDN

DNS updated to new deployment

Old deployment kept for rollback
Deployment time: ~2-3 minutes

Preview Deployment

Developer opens PR

Vercel creates preview
  ├── URL: charle-os-git-{branch}.vercel.app
  ├── Uses Preview environment variables
  └── Links to PR for easy access

Update PR → Preview auto-updates
Preview features:
  • Unique URL per branch
  • Shareable for testing
  • Auto-deleted after PR merge
  • Comments added to PR with preview URL

Vercel Features

Analytics

Built-in analytics show:
  • Web Vitals: LCP, FID, CLS, TTFB
  • Top Pages: Most visited pages
  • Top Referrers: Traffic sources
  • Real User Monitoring: Actual user experience
Access: Dashboard → Analytics

Logs

Real-time logs for debugging: Build Logs:
  • Dependency installation
  • Database migration output
  • Build errors/warnings
Runtime Logs:
  • API route requests
  • Server component logs
  • Error stack traces
Edge Logs:
  • Edge function execution
  • Regional performance
Access: Dashboard → Deployments → Select deployment → Logs

Speed Insights

Track performance metrics:
  • Real User Monitoring (RUM)
  • Core Web Vitals breakdown
  • Page-by-page performance
  • Regional performance data

Monitoring

Uptime and performance monitoring:
  • 99.99% uptime SLA
  • Automated health checks
  • Incident notifications
  • Status page

Custom Domains

CharleOS uses custom domains:

Main App

Domain: charle.agency
DNS: Managed by Cloudflare
SSL: Automatic (Vercel)
DNS Configuration:
CNAME @ cname.vercel-dns.com

Client Portal

Domain: clients.charle.agency
Subdomain: Separate Next.js app deployment
DNS Configuration:
CNAME clients cname.vercel-dns.com

Performance Optimization

Caching

Vercel automatically caches: Static Assets:
Cache-Control: public, max-age=31536000, immutable
Server Components:
Cache-Control: s-maxage=60, stale-while-revalidate
API Routes:
// Custom cache headers
export async function GET(req: Request) {
  return Response.json(data, {
    headers: {
      'Cache-Control': 'public, s-maxage=300, stale-while-revalidate=600',
    },
  });
}

Image Optimization

Next.js Image component uses Vercel’s optimizer:
import Image from "next/image";

<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority  // Preload for above-fold images
/>
Optimizations:
  • Automatic WebP/AVIF conversion
  • Responsive sizing
  • Lazy loading
  • CDN caching

Edge Functions

API routes run on Vercel Edge (close to users):
// app/api/fast/route.ts
export const runtime = 'edge';  // Run on edge

export async function GET() {
  return Response.json({ message: "Fast response!" });
}

Security

HTTPS/SSL

  • Automatic SSL certificate provisioning
  • TLS 1.3 encryption
  • HTTP → HTTPS redirect
  • HSTS enabled

DDoS Protection

Vercel provides:
  • Edge network DDoS mitigation
  • Automatic rate limiting
  • IP blocking for abuse

Security Headers

// next.config.ts
const securityHeaders = [
  { key: 'X-DNS-Prefetch-Control', value: 'on' },
  { key: 'Strict-Transport-Security', value: 'max-age=63072000' },
  { key: 'X-Frame-Options', value: 'SAMEORIGIN' },
  { key: 'X-Content-Type-Options', value: 'nosniff' },
  { key: 'Referrer-Policy', value: 'origin-when-cross-origin' },
];

module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: securityHeaders,
      },
    ];
  },
};

Vercel CLI

Installation

npm install -g vercel

Common Commands

# Link project
vercel link

# Deploy to production
vercel --prod

# Deploy to preview
vercel

# View deployments
vercel ls

# View logs
vercel logs

# Pull environment variables
vercel env pull .env.local

# Add environment variable
vercel env add DATABASE_URL production

# Remove deployment
vercel remove [deployment-url]

Troubleshooting

Build Failures

Error: “Command ‘npm run build’ exited with 1” Fix:
  1. Check build logs in Vercel dashboard
  2. Run npm run build locally
  3. Fix TypeScript errors
  4. Check environment variables are set
  5. Verify migrations don’t have errors

Deployment Timeout

Error: “Build exceeded maximum duration” Fix:
  • Optimize build (remove unnecessary dependencies)
  • Enable build cache
  • Contact Vercel support for timeout increase

Environment Variable Not Found

Error: “Missing environment variable: X” Fix:
  1. Go to Vercel Dashboard → Settings → Environment Variables
  2. Add missing variable
  3. Select correct environments (Production/Preview)
  4. Redeploy

Domain Not Resolving

Error: “ERR_NAME_NOT_RESOLVED” Fix:
  1. Check DNS configuration in Cloudflare
  2. Verify CNAME points to cname.vercel-dns.com
  3. Wait for DNS propagation (up to 48 hours)
  4. Use dig charle.agency to check DNS

Best Practices

Always test in preview before merging:
  1. Open PR
  2. Wait for preview deployment
  3. Test preview URL thoroughly
  4. Merge to main when confirmed working
Use different credentials for preview:
  • Production: Real database, real API keys
  • Preview: DEV database, test API keys
  • Never mix environments
Check Vercel Analytics after deploying:
  • Verify traffic is flowing
  • Check for errors in logs
  • Monitor Core Web Vitals
Optimize build time:
  • Remove unused dependencies
  • Enable build caching
  • Minimize dynamic imports