Deployment

This guide covers deploying AllyProof to production, including Supabase setup, database migrations, pg_cron configuration, Playwright installation, and building the Next.js application.

Prerequisites

  • Node.js 20+ and npm
  • A Supabase project (free tier works for development)
  • Supabase CLI installed (npm install -g supabase)
  • Environment variables configured (see Environment Variables)

1. Supabase Setup

Create a project

Create a new Supabase project at supabase.com/dashboard. Note your project URL and keys from the API settings page.

Link the CLI

npx supabase login
npx supabase link --project-ref your-project-ref

Enable required extensions

Go to Database > Extensions in the Supabase dashboard and enable:

  • pg_cron — Required for scheduled scans
  • pg_net — Required for pg_cron to make HTTP calls
  • pgcrypto — Used for UUID generation (usually enabled by default)

2. Database Migrations

Apply all pending migrations to your Supabase database:

# Push migrations to remote database
npx supabase db push

# Verify tables were created
npx supabase db inspect

Migrations create all tables, RLS policies, indexes, and functions. See the Database Schema page for table details.

Seed data (optional)

# Apply seed data for development/staging
npx supabase db seed

3. Configure pg_cron

Set up the scheduled scan cron jobs. First, configure the application settings that pg_cron needs to call the trigger endpoint:

-- Run in Supabase SQL Editor
ALTER DATABASE postgres SET app.settings.app_url = 'https://app.allyproof.com';
ALTER DATABASE postgres SET app.settings.cron_secret = 'your-cron-secret-here';

Then create the cron jobs:

-- Daily scans at 03:00 UTC
SELECT cron.schedule(
  'trigger-daily-scans',
  '0 3 * * *',
  $$
  SELECT net.http_post(
    url := current_setting('app.settings.app_url') || '/api/internal/trigger-scheduled-scans',
    headers := jsonb_build_object(
      'Content-Type', 'application/json',
      'Authorization', 'Bearer ' || current_setting('app.settings.cron_secret')
    ),
    body := '{"frequency": "daily"}'::jsonb
  );
  $$
);

-- Weekly scans on Mondays at 03:00 UTC
SELECT cron.schedule(
  'trigger-weekly-scans',
  '0 3 * * 1',
  $$
  SELECT net.http_post(
    url := current_setting('app.settings.app_url') || '/api/internal/trigger-scheduled-scans',
    headers := jsonb_build_object(
      'Content-Type', 'application/json',
      'Authorization', 'Bearer ' || current_setting('app.settings.cron_secret')
    ),
    body := '{"frequency": "weekly"}'::jsonb
  );
  $$
);

See the Scheduled Scans guide for more details.

4. Install Playwright

Playwright is used by the scanning engine to render pages. Install the browsers:

# Install Playwright browsers (Chromium is required)
npx playwright install chromium

# On Linux servers, install system dependencies
npx playwright install-deps chromium

In Docker environments, use the official Playwright base image which includes all dependencies:

FROM mcr.microsoft.com/playwright:v1.49.0-noble
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build

5. Production Build

# Install dependencies
npm ci

# Run type checking
npx tsc --noEmit

# Build the application
npm run build

# Start the production server
npm start

The build produces a .next/ directory with the optimized production output. The npm start command runs the Next.js production server on port 3000 by default.

6. Docker Deployment

For containerized deployments, use the included Dockerfile:

# Build the Docker image
docker build -t allyproof .

# Run with environment variables
docker run -p 3000:3000 \
  --env-file .env.production \
  allyproof

Docker Compose (development)

# Start all services (app + local Supabase)
docker compose up -d

# View logs
docker compose logs -f app

7. Production Checklist

Before going live, verify:

ItemCheck
Environment variablesAll required variables set (see env reference)
Database migrationsnpx supabase db push completed without errors
RLS policiesAll tables have RLS enabled and policies applied
pg_cron jobsScheduled scan cron jobs created and CRON_SECRET matches
PlaywrightChromium installed and system dependencies present
Resend domainSending domain verified with SPF/DKIM records
Paddle webhooksWebhook endpoint URL configured in Paddle dashboard
SentryDSN configured for error tracking
SSL/TLSHTTPS enforced on all endpoints
Build passesnpm run build completes without errors or warnings

Troubleshooting

ProblemSolution
Playwright fails to launchRun npx playwright install-deps chromium to install OS dependencies
Supabase connection refusedVerify NEXT_PUBLIC_SUPABASE_URL and keys are correct
Migrations failCheck for pending migrations with npx supabase migration list
Emails not sendingVerify RESEND_API_KEY and that the sending domain is verified
pg_cron not firingEnsure pg_cron and pg_net extensions are enabled