Guides

Deployment

Deploy nuxt-crouton applications to production

Deployment Guide

This guide covers deploying nuxt-crouton applications to production environments.

Deployment Targets

nuxt-crouton apps are built on Nuxt and can deploy to any platform that supports Nuxt:

PlatformDatabaseRecommended For
Cloudflare PagesD1 (SQLite)Production apps (recommended)
VercelTurso/PlanetScaleVercel-native workflows
NetlifyTurso/PlanetScaleNetlify-native workflows
Self-hostedAny SQLite/PostgreSQLFull control
Recommended: Cloudflare Pages with D1 provides the best experience for nuxt-crouton apps with edge computing, low latency, and integrated SQLite.

Cloudflare Pages Deployment

Prerequisites

  1. Cloudflare Account with Pages enabled
  2. Wrangler CLI installed:
    npm install -g wrangler
    
  3. Authentication:
    wrangler login
    

Step 1: Create Cloud Resources

Create D1 Database

# Create the database
wrangler d1 create my-app-db

# Output will include database_id - save this!
# ✅ Successfully created DB 'my-app-db'
# database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Create KV Namespace

# Create KV for sessions/cache
wrangler kv:namespace create KV

# Output will include the id - save this!
# ✅ Successfully created KV namespace "KV"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Step 2: Configure wrangler.toml

Create or update wrangler.toml in your app directory:

name = "my-app"
compatibility_date = "2024-09-02"
compatibility_flags = ["nodejs_compat"]
pages_build_output_dir = "dist"

[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "your-database-id-here"

[[kv_namespaces]]
binding = "KV"
id = "your-kv-id-here"

Step 3: Configure Nuxt

Ensure your nuxt.config.ts is configured for Cloudflare:

export default defineNuxtConfig({
  // ... your extends

  // CRITICAL: Use db: 'sqlite', NOT database: true
  hub: {
    db: 'sqlite',
    kv: true
  },

  // Disable incompatible features
  croutonAuth: {
    passkeys: false  // Not supported on Cloudflare Workers
  }
})
Common Mistake: Using hub: { database: true } will cause build failures. Always use hub: { db: 'sqlite' }.

Step 4: Set Environment Variables

Required Variables

VariableDescriptionExample
BETTER_AUTH_SECRETSession encryption (32+ chars)Generate with openssl rand -base64 32
BETTER_AUTH_URLProduction URLhttps://my-app.pages.dev

Setting via CLI

# Generate a secure secret
openssl rand -base64 32

# Add to Cloudflare
npx wrangler pages secret put BETTER_AUTH_SECRET
# Paste the generated secret when prompted

npx wrangler pages secret put BETTER_AUTH_URL
# Enter your production URL

Setting via Dashboard

  1. Go to dash.cloudflare.com
  2. Navigate to Workers & Pagesyour-app
  3. Go to SettingsEnvironment Variables
  4. Add variables for Production (and Preview if needed)
  5. Click Save

Step 5: Run Database Migrations

# Generate migrations (if not already done)
pnpm run db:generate

# Apply to production D1
pnpm run db:migrate:prod
# or: npx wrangler d1 migrations apply my-app-db --remote
Important: Always run migrations before deploying code that depends on schema changes.

Step 6: Deploy

# Build and deploy to production
pnpm run cf:deploy
# or: nuxt build && npx wrangler pages deploy dist

For preview deployments:

pnpm run cf:preview
# or: nuxt build && npx wrangler pages deploy dist --branch preview

OAuth Configuration

Google OAuth

  1. Create credentials at Google Cloud Console
  2. Add authorized redirect URI: https://your-domain.com/api/auth/callback/google
  3. Set environment variables:
    npx wrangler pages secret put GOOGLE_CLIENT_ID
    npx wrangler pages secret put GOOGLE_CLIENT_SECRET
    

GitHub OAuth

  1. Create OAuth app at GitHub Settings
  2. Set callback URL: https://your-domain.com/api/auth/callback/github
  3. Set environment variables:
    npx wrangler pages secret put GITHUB_CLIENT_ID
    npx wrangler pages secret put GITHUB_CLIENT_SECRET
    

Cloudflare Worker Limitations

Some features are disabled or limited on Cloudflare Workers:

FeatureStatusReasonWorkaround
Passkeys/WebAuthnDisabledtsyringe incompatibleUse email/password or OAuth
OG Image GenerationOptionalReduces bundle (~4MB)Use static OG images
Long-running tasksLimited30s CPU limitUse Cloudflare Queues

Configuration for disabled features:

// nuxt.config.ts
export default defineNuxtConfig({
  croutonAuth: {
    passkeys: false
  }
})

Deployment Checklists

First-Time Deployment

  • Create Cloudflare account and wrangler login
  • Create D1 database: wrangler d1 create {app}-db
  • Create KV namespace: wrangler kv:namespace create KV
  • Update wrangler.toml with database_id and KV id
  • Set BETTER_AUTH_SECRET (32+ character secret)
  • Set BETTER_AUTH_URL (your production URL)
  • Configure OAuth providers (if using)
  • Run pnpm run db:migrate:prod
  • Deploy: pnpm run cf:deploy
  • Test registration and login
  • Verify OAuth flows (if configured)

Subsequent Deployments

  • If schema changed: pnpm run db:generate
  • If schema changed: pnpm run db:migrate:prod
  • Deploy: pnpm run cf:deploy
  • Verify app functionality

Troubleshooting

BETTER_AUTH_SECRET is required

Cause: Environment variable not set in Cloudflare.

Fix:

openssl rand -base64 32  # Generate secret
npx wrangler pages secret put BETTER_AUTH_SECRET
# Paste the generated secret

Then redeploy.

Cannot resolve entry module .nuxt/hub/db/schema.entry.ts

Cause: Using hub: { database: true } instead of hub: { db: 'sqlite' }.

Fix: Update nuxt.config.ts:

hub: {
  db: 'sqlite',  // NOT database: true
  kv: true
}

Database migrations fail

Cause: Database not created or wrong database_id.

Fix:

  1. Verify database exists: wrangler d1 list
  2. Check wrangler.toml has correct database_id
  3. Run: wrangler d1 migrations apply {app}-db --remote

OAuth callback fails

Cause: Callback URL mismatch or missing BETTER_AUTH_URL.

Fix:

  1. Ensure BETTER_AUTH_URL is set to your production URL
  2. Verify OAuth provider callback URLs match exactly:
    • Google: https://your-domain.com/api/auth/callback/google
    • GitHub: https://your-domain.com/api/auth/callback/github

Build errors with passkeys

Cause: Passkey dependencies are incompatible with Workers.

Fix: Disable passkeys in config:

croutonAuth: {
  passkeys: false
}

Useful Commands

# Wrangler Management
wrangler login                # Authenticate
wrangler d1 list              # List databases
wrangler kv:namespace list    # List KV namespaces
wrangler pages secret list    # List secrets
wrangler pages secret put X   # Add secret X
wrangler tail                 # View live logs

# Database Operations
pnpm run db:generate          # Generate migrations
pnpm run db:migrate           # Apply locally
pnpm run db:migrate:prod      # Apply to production

# Deployment
pnpm run cf:deploy            # Deploy production
pnpm run cf:preview           # Deploy preview

Alternative Platforms

Vercel

  1. Configure for Vercel in nuxt.config.ts:
    export default defineNuxtConfig({
      nitro: {
        preset: 'vercel'
      }
    })
    
  2. Use Turso or PlanetScale for database
  3. Set environment variables in Vercel dashboard
  4. Deploy via Vercel CLI or Git integration

Self-Hosted

  1. Build the application:
    nuxt build
    
  2. Run with Node.js:
    node .output/server/index.mjs
    
  3. Use SQLite file or configure PostgreSQL
  4. Set environment variables on your server
  5. Use PM2, systemd, or Docker for process management