Skip to content

Deployment Guide

Platform: Cloudflare Pages + Workers
Adapter: OpenNext for Cloudflare
CI/CD: GitHub Actions

Overview

The Eventify platform is deployed to Cloudflare using the OpenNext adapter, which translates Next.js App Router features to Cloudflare Workers. Deployments are automated via GitHub Actions for three environments:

  • Production - Main branch → https://eventify.today
  • Staging - Staging branch → https://staging.eventify.today
  • Preview - Pull requests with deploy-preview label → Temporary URLs

Required GitHub Secrets

Configure these in Settings → Secrets and variables → Actions:

Cloudflare

  • CLOUDFLARE_API_TOKEN - API token with Cloudflare Pages permissions
  • CLOUDFLARE_ACCOUNT_ID - Your Cloudflare account ID

Authentication

  • NEXTAUTH_SECRET - NextAuth.js session encryption key (min 32 chars)

Email

  • BREVO_API_KEY - Brevo API v3 key for transactional emails

Payments

  • STRIPE_SECRET_KEY - Stripe secret API key
  • STRIPE_WEBHOOK_SECRET_KEY - Stripe webhook signing secret

Maps

  • MAPBOX_TOKEN - Mapbox API token for maps functionality

Environment Variables (wrangler.jsonc)

Non-secret configuration is stored in wrangler.jsonc:

{
  "name": "eventify-next",
  "compatibility_flags": ["nodejs_compat"],
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "eventify-db",
      "database_id": "your-database-id"
    }
  ],
  "vars": {
    "NODE_ENV": "production",
    "NEXTAUTH_URL": "https://eventify.today",
    "SITE_URL": "https://eventify.today",
    "EMAIL_FROM": "noreply@eventify.today",
    "EMAIL_FROM_NAME": "Eventify",
    "STRIPE_PUBLISHABLE_KEY": "pk_live_...",
    "GA_ID": "G-XXXXXXXXXX"
  }
}

Environment-Specific Configuration

The file contains sections for development, staging, and production. Each environment can override variables as needed.

Example for staging:

{
  "env": {
    "staging": {
      "name": "eventify-next-staging",
      "vars": {
        "NODE_ENV": "staging",
        "NEXTAUTH_URL": "https://staging.eventify.today",
        "STRIPE_PUBLISHABLE_KEY": "pk_test_..."
      }
    }
  }
}

GitHub Actions Workflows

Production Deployment

File: .github/workflows/deploy-production.yml
Trigger: Push to main branch

Steps: 1. Checkout code 2. Install dependencies 3. Run Prisma generation 4. Build with OpenNext adapter (npm run build:opennext) 5. Deploy to Cloudflare Pages via Wrangler 6. Set secrets via Wrangler CLI

Environment: Uses production from wrangler.jsonc

Staging Deployment

File: .github/workflows/deploy-staging.yml
Trigger: Push to staging branch

Steps: Same as production but uses staging environment

Preview Deployment

File: .github/workflows/pr-validation-and-preview.yml
Trigger: Pull requests with deploy-preview label

Steps: 1. Run tests and validation 2. Build preview version 3. Deploy to temporary Cloudflare URL 4. Post preview URL in PR comments 5. Overrides NEXTAUTH_URL to match preview URL

Note: Preview deployments use development configuration as base.

Setting Up Secrets

GitHub Repository Secrets

  1. Navigate to Settings → Secrets and variables → Actions
  2. Click New repository secret
  3. Add each secret from the required list above

Generate NEXTAUTH_SECRET:

openssl rand -base64 32

Cloudflare Secrets

For local development and manual deployments:

# Set secret for production
wrangler secret put NEXTAUTH_SECRET --env production

# Set secret for staging
wrangler secret put NEXTAUTH_SECRET --env staging

# List all secrets
wrangler secret list

Note: GitHub Actions automatically sets secrets during deployment, so manual wrangler secret put is only needed for local testing.

Database Deployment

D1 Migrations

Migrations are applied automatically during deployment, but you can run them manually:

# Apply to production
wrangler d1 migrations apply DB --env production --remote

# Apply to staging
wrangler d1 migrations apply DB --env staging --remote

# List pending migrations
wrangler d1 migrations list DB --env production

Creating Migrations

# Generate migration from Prisma schema
npx prisma migrate dev --name your_migration_name

# This creates files in prisma/migrations/

Seeding Production Data

Warning: Only seed production if intentional!

# Use production seed script
npm run seed:prod

Build Process

Local Build

npm run build:opennext

This runs: 1. Prisma client generation 2. Next.js build 3. OpenNext adapter transformation 4. Output to .open-next/ directory

Build Configuration

File: open-next.config.ts

export default {
  default: {
    override: {
      wrapper: "cloudflare-node",
      converter: "edge",
      incrementalCache: "r2",
    },
  },
};

Features: - Cloudflare Workers wrapper - Edge runtime converter - R2 for incremental static regeneration cache

Preview Deployments

Triggering Preview

  1. Create a pull request
  2. Add the deploy-preview label
  3. GitHub Actions will automatically deploy
  4. Preview URL posted as PR comment

Preview Limitations

  • Uses development D1 database
  • Temporary URL expires after PR is closed
  • Secrets shared with development environment

Deployment Checklist

Initial Setup (One-time)

  • Create Cloudflare account
  • Create D1 database for each environment
  • Update wrangler.jsonc with database IDs
  • Configure custom domain in Cloudflare Pages
  • Add all GitHub secrets
  • Set up DNS records

Before Each Deployment

  • Run tests locally: npm run test
  • Verify build: npm run build:opennext
  • Check Prisma migrations are generated
  • Review environment variables in wrangler.jsonc
  • Ensure secrets are up to date

After Deployment

  • Verify deployment in Cloudflare dashboard
  • Test authentication flows
  • Check email sending (Brevo)
  • Test Stripe payments (webhook endpoint)
  • Monitor Cloudflare Workers logs
  • Verify D1 database connections

Monitoring & Logs

Cloudflare Dashboard

  • Workers Logs: Real-time request/error logs
  • D1 Analytics: Query performance and usage
  • Pages Deployments: Build history and status

Viewing Logs Locally

# Tail production logs
wrangler tail --env production

# Tail staging logs
wrangler tail --env staging

Brevo Dashboard

  • Email Stats: Delivery rates, bounces, opens
  • API Usage: Daily quota and usage
  • Webhook Logs: Email events (if configured)

Stripe Dashboard

  • Webhooks: Delivery status and retry history
  • Payments: Transaction history
  • Test Mode: Separate dashboard for test keys

Troubleshooting

Deployment Fails

Check GitHub Actions logs: 1. Go to Actions tab in GitHub 2. Select failed workflow 3. Review step-by-step logs

Common issues: - Missing secrets → Add in GitHub settings - Build errors → Run npm run build:opennext locally - D1 connection errors → Verify database ID in wrangler.jsonc

Environment Variables Not Working

Secrets:

# Verify secret is set
wrangler secret list --env production

# Re-set if missing
wrangler secret put SECRET_NAME --env production

Variables: - Check wrangler.jsonc syntax (valid JSON) - Ensure environment section matches deployment target - Restart deployment after changes

Database Migration Issues

# Force reset (DESTRUCTIVE - development only)
wrangler d1 migrations apply DB --env development --remote --force

# Check migration status
wrangler d1 migrations list DB --env production

NEXTAUTH_URL Mismatch

Symptom: Authentication redirects to wrong domain

Fix: Update NEXTAUTH_URL in wrangler.jsonc for correct environment:

{
  "vars": {
    "NEXTAUTH_URL": "https://eventify.today",
    "SITE_URL": "https://eventify.today"
  }
}

Stripe Webhooks Not Received

  1. Verify webhook endpoint in Stripe dashboard: https://eventify.today/api/webhooks/stripe
  2. Check STRIPE_WEBHOOK_SECRET_KEY matches Stripe dashboard
  3. Monitor Stripe webhook logs for delivery errors
  4. Test locally with Stripe CLI: stripe listen --forward-to localhost:3000/api/webhooks/stripe

Local Development

Environment Setup

  1. Copy example file:

    cp .dev.vars.example .dev.vars
    

  2. Fill in secrets in .dev.vars:

    NEXTAUTH_SECRET=your-local-secret
    BREVO_API_KEY=xkeysib-your-key
    GOOGLE_CLIENT_SECRET=your-google-secret
    STRIPE_SECRET_KEY=sk_test_...
    STRIPE_WEBHOOK_SECRET_KEY=whsec_...
    MAPBOX_TOKEN=your-mapbox-token
    

  3. Start development server:

    npx wrangler dev
    

Note: .dev.vars is gitignored and never committed.

Testing Locally with D1

Wrangler creates a local SQLite database:

.wrangler/state/v3/d1/miniflare-D1Database/<id>.sqlite

You can inspect it with SQLite CLI:

sqlite3 .wrangler/state/v3/d1/miniflare-D1Database/<id>.sqlite

Additional Resources

  • Cloudflare D1: https://developers.cloudflare.com/d1/
  • Cloudflare Pages: https://developers.cloudflare.com/pages/
  • OpenNext Cloudflare: https://opennext.js.org/cloudflare
  • Wrangler CLI: https://developers.cloudflare.com/workers/wrangler/
  • GitHub Actions: https://docs.github.com/en/actions