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
| Setting | Value |
|---|---|
| Build command | npm run build |
| Publish directory | dist |
| Node version | 18+ |
| Configuration file | netlify.toml |
Manual Deploy
If you need to trigger a deploy without pushing code:
- Go to the Netlify dashboard
- Select the Client Portal site
- Click Trigger deploy > Deploy site
Environment Variables on Netlify
Set these in the Netlify dashboard under Site settings > Build & deploy > Environment:
VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEY
These are baked into the build at compile time (Vite replaces import.meta.env.VITE_* references).
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
attorneystable 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 resetbefore 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:
- Go to Netlify dashboard > Deploys
- Find the last working deploy
- Click Publish deploy
Edge Functions
Edge functions do not have built-in rollback. To revert:
git checkoutthe previous version of the function- Redeploy:
supabase functions deploy <function-name>
Database
Database migrations cannot be automatically rolled back. If a migration causes issues:
- Write a new migration that reverses the changes
- Apply it with
supabase db push - Never manually edit the
supabase_migrationstracking table