Overview
The Supabase project lives under supabase/ at the repo root. It owns:
supabase/
├── functions/ # Edge Functions (Deno)
│ ├── _shared/ # Reusable auth + client helpers
│ ├── get-permissions-snapshot/
│ ├── send-email/
│ ├── generate-chart-data/
│ ├── refresh-all-charts/
│ └── sync-to-redis/
├── migrations/ # SQL schema migrations (timestamped)
├── snippets/ # Saved SQL snippets used during development
├── templates/ # Auth email templates
├── seed.sql # Seed data for local dev
└── config.toml # Supabase CLI / local-dev configuration
Edge Functions at a glance
| Function | Trigger | Purpose |
|---|---|---|
get-permissions-snapshot | Called by getRoutePermissions (RSC) | Resolves { teamAccess, campaignAccess?, permissionKeys? } for a (user, team?, campaign?) |
send-email | sendInviteEmailViaEdge from server actions | SMTP delivery of invitation / notification emails |
generate-chart-data | refresh-all-charts (and may be called manually) | Generates and stores charts.data for one chart from its declarative ChartConfig |
refresh-all-charts | Manual / scheduled | Iterates over every row in charts and triggers generate-chart-data per chart, in parallel |
sync-to-redis | Database trigger / server actions | Adds or removes voter IDs in the campaign:{id}:signers Redis set |
See Edge Functions for full details.
Shared utilities (_shared/)
_shared/auth.tsexposesrequireAuth(req)which validates the bearer JWT and returns:type AuthSuccess = { ok: true; caller: User; supabaseAdmin: SupabaseClient };
type AuthFailure = { ok: false; response: Response };_shared/supabase.tsexposes:createServiceRoleClient()— service-role client (admin).createUserClient(authorization)— user-scoped client honoring RLS via the bearer token.
Functions that need to act on behalf of the caller call requireAuth(req) first and then use either caller or supabaseAdmin depending on whether RLS should apply.
Migrations
Migrations are timestamped SQL files in supabase/migrations/. They are applied via the Supabase CLI. Notable themes (latest at the top):
2026-04-22 …_supabase_verify.sql— JWT verification + signing-key updates.2026-04 …_campaign_team_sets.sql,_campaign_policies.sql,_drop_old_campaign_permission_table.sql— campaign permission-set refactor (foundation for the newget-permissions-snapshotfunction).2026-04 …_redis_sync_function_trig_dropped.sql— removes the database trigger that called thesync-to-redisfunction on every signature change. Sync now happens explicitly from the application layer.2026-03 …_regions_table.sql,_regions.sql— region (sub-area) support.2026-02 …_tran_campaign.sql,_rates_campaign.sql— campaign-scoped rates and transactions.2026-01 …_turn-in-tables.sql— turn-in tracking.2025-12 …_charts-table.sql,_charts-table.sql— configurable charts that back the dashboards builder.
Local development
Use the Supabase CLI:
supabase start # boots Postgres, Auth, Storage, Edge Runtime
supabase functions serve <function> # runs a single function locally with hot reload
supabase db push # applies new migrations to the local DB
supabase db reset # drops and re-seeds from seed.sql
Required environment variables (server-side):
SUPABASE_URL,SUPABASE_ANON_KEY,SUPABASE_SERVICE_ROLE_KEYSMTP_HOST,SMTP_PORT,SMTP_USERNAME,SMTP_PASSWORD,SMTP_SENDER_EMAIL,SMTP_SENDER_NAME(forsend-email)REDIS_URL(forsync-to-redis)