Skip to main content

Deployment Guide

How to deploy Client Portal frontend, edge functions, and database changes.

Frontend (Netlify)

The React frontend is hosted on Netlify and deploys automatically.

Auto-Deploy

Pushing to the main branch triggers an automatic build and deploy:

git push origin main

Netlify watches the main branch and runs the build pipeline on every push.

Build Configuration

SettingValue
Build commandnpm run build
Publish directorydist
Node version18+
Configuration filenetlify.toml

Manual Deploy

If you need to trigger a deploy without pushing code:

  1. Go to the Netlify dashboard
  2. Select the Client Portal site
  3. Click Trigger deploy > Deploy site

Environment Variables on Netlify

Set these in the Netlify dashboard under Site settings > Build & deploy > Environment:

  • VITE_SUPABASE_URL
  • VITE_SUPABASE_ANON_KEY

These are baked into the build at compile time (Vite replaces import.meta.env.VITE_* references).

caution

Never set SUPABASE_SERVICE_ROLE_KEY on Netlify. The service role key should only exist in local .env files and Supabase secrets -- never in the client bundle.

Edge Functions (Supabase)

Edge functions are Deno functions that run on Supabase infrastructure.

Deploy a Single Function

supabase functions deploy <function-name>

Example:

supabase functions deploy summarize-sales-call
supabase functions deploy ghl-call-webhook
supabase functions deploy sync-prospects-to-ghl

Deploy All Functions

supabase functions deploy

This deploys every function in supabase/functions/.

Set Secrets

Edge functions access secrets via Deno.env.get(). Set them with:

supabase secrets set ANTHROPIC_API_KEY=sk-ant-...
supabase secrets set BLITZ_API_KEY=...
supabase secrets set RESEND_API_KEY=re_...

List current secrets:

supabase secrets list

JWT Verification

Most webhook endpoints need verify_jwt = false because external services (GHL, Fathom, etc.) cannot send Supabase JWTs. This is configured in supabase/config.toml:

[functions.<function-name>]
verify_jwt = false

After changing config.toml, redeploy the affected function.

Verify Deployment

After deploying, verify the function is live:

curl -X POST \
https://<supabase-url>/functions/v1/<function-name> \
-H "Authorization: Bearer <anon-key>" \
-H "Content-Type: application/json" \
-d '{}'

Check the response status and body. Also check Supabase Dashboard > Edge Functions > Logs for invocation records.

Database Migrations

Apply Migrations

Push all pending migrations to the remote database:

supabase db push

This applies any migration files in supabase/migrations/ that have not yet been applied.

Create a New Migration

supabase migration new <description>

Example:

supabase migration new add_ghl_custom_fields

This creates a new timestamped SQL file in supabase/migrations/. Write your DDL changes in this file, then apply with supabase db push.

Migration Naming Convention

Migration files are named with a timestamp prefix:

20260210100000_add_ghl_integrations.sql
20260210200001_convert_disposition_to_text.sql
20260208100000_add_internal_sales.sql
20260208120000_add_internal_booking.sql

Format: YYYYMMDDHHMMSS_<description>.sql

Important Notes on Migrations

  • The attorneys table was created via the Supabase dashboard, not through migration files. Changes to this table should still be done via migrations going forward.
  • Always test migrations locally first with supabase db reset before pushing to production.
  • Migrations are applied in order of their timestamp prefix.

Deployment Checklist

Use this checklist for non-trivial deployments:

Before Deploying

  • All changes are committed and pushed to main
  • Local build succeeds (npm run build)
  • Lint passes (npm run lint)
  • Any new environment variables are set on Netlify and/or Supabase secrets
  • Database migrations are tested locally

After Deploying

  • Netlify build completed successfully (check Netlify dashboard)
  • Edge functions are responding (test with curl)
  • Webhooks are still working (check webhook_debug_log)
  • No new errors in Supabase edge function logs
  • Smoke test: log in as admin, client, and BDR roles

Rollback

Frontend

Netlify keeps previous deploys. To rollback:

  1. Go to Netlify dashboard > Deploys
  2. Find the last working deploy
  3. Click Publish deploy

Edge Functions

Edge functions do not have built-in rollback. To revert:

  1. git checkout the previous version of the function
  2. Redeploy: supabase functions deploy <function-name>

Database

Database migrations cannot be automatically rolled back. If a migration causes issues:

  1. Write a new migration that reverses the changes
  2. Apply it with supabase db push
  3. Never manually edit the supabase_migrations tracking table