Supabase Setup

Set up Supabase auth, database, storage, and Edge Functions.

Supabase backs the Expo template's Auth, Postgres data, private Storage, Edge Functions, and account-bound entitlement read model. Unlike the native Swift sibling, this template ships the full app schema as migrations, so supabase db push can stand up the working backend in one pass.

Create the project

Create a Supabase project

Create a project in the Supabase dashboard, then copy the project URL and anon key from Project Settings → API into soar-expo/.env.local:

EXPO_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_PROJECT_ID=your-project-ref

The URL and anon key are public client values. Keep service-role keys out of Expo env files.

brew install supabase/tap/supabase
supabase login
supabase link --project-ref <ref>

supabase/config.toml includes the per-function JWT settings the template relies on.

Apply every migration

supabase db push --project-ref <ref>

The repository ships four migrations:

MigrationWhat it creates
20240101000000_init_profiles.sqlprofiles, RLS, and a sign-up trigger that copies full_name from user metadata
20240101000001_init_todos.sqltodos, ordering indexes, updated_at trigger, and owner-scoped CRUD policies
20240101000003_step7_examples.sqlsample_uploads, private sample-uploads bucket, 50 MB limit, and folder-scoped Storage policies
20260630120000_billing_entitlements.sqlsubscriptions and payments, shared with soar-electron; clients get SELECT-only RLS

All migrations use if not exists, create or replace, or guarded policies, so re-applying them is safe. If you cannot use the CLI, paste the migration SQL files into the dashboard SQL editor in timestamp order.

Generate client types

pnpm gen:types

The script runs Supabase type generation against SUPABASE_PROJECT_ID and writes types/database.ts. Re-run it after any schema change before writing new app queries.

Auth URLs

The current app uses typed OTP entry for email flows and native ID-token sign-in for Apple and Google:

  • Email sign-up and password reset call Supabase Auth, then verify the code in the app.
  • Apple and Google call supabase.auth.signInWithIdToken(...), so Supabase does not redirect back into the app.

For this code path, there is no app callback route to implement. Still set a dashboard Site URL for local web testing:

http://localhost:3000

If you later change a flow to link-based OAuth or magic links, allow the variant schemes from app.config.ts:

soar-starter-expo-dev://
soar-starter-expo-preview://
soar-starter-expo://

For Google native sign-in, the Supabase provider itself still needs the standard provider callback URL in the Google Cloud Web OAuth client:

https://<ref>.supabase.co/auth/v1/callback

See Authentication for Apple and Google setup.

Edge Functions

Deploy the functions from soar-expo/supabase/functions:

supabase functions deploy revenuecat-webhook --no-verify-jwt --project-ref <ref>
supabase functions deploy delete-account --project-ref <ref>

# Optional APNs debug artifact:
supabase functions deploy send-test-push --project-ref <ref>

functions/_shared/ is bundled into the functions that import it. Do not deploy _shared by itself.

FunctionJWTPurpose
revenuecat-webhookOffRevenueCat calls it without a Supabase JWT; it verifies the static Authorization header and writes subscriptions / payments with the service role
delete-accountOnSigned-in users call it to delete rows, files under sample-uploads/<user-id>/, then the auth user
send-test-pushOnOptional APNs sender copied from the Swift template; it expects a device_tokens table the Expo template does not ship

The Expo client gets an Expo push token in lib/notifications.tsx, but it does not persist tokens to Supabase. Treat send-test-push as an optional backend artifact until you add a token table and registration flow.

Edge secrets

Set only server-side secrets in Supabase:

supabase secrets set REVENUECAT_WEBHOOK_AUTH=<long-random-string> --project-ref <ref>
SecretUsed byNotes
REVENUECAT_WEBHOOK_AUTHrevenuecat-webhookMust match the RevenueCat webhook Authorization header
APNS_TEAM_IDsend-test-pushOptional Apple Developer Team ID
APNS_KEY_IDsend-test-pushOptional APNs auth key ID
APNS_BUNDLE_IDsend-test-pushOptional iOS bundle ID such as expo.soarstarter.com
APNS_PRIVATE_KEYsend-test-pushOptional .p8 private key contents

Do not set SUPABASE_URL, SUPABASE_ANON_KEY, or the service-role key as Edge secrets. Supabase injects the runtime values automatically.

Local function development

supabase functions serve --env-file supabase/functions/.env
deno test supabase/functions/_shared/revenuecat.test.ts

functions serve exposes local functions under http://localhost:54321/functions/v1/....

Verify the backend

  • Sign up in the app, verify the email code, and confirm a profiles row appears for the user.
  • Create, edit, reorder, and delete todos; relaunch and confirm they persist.
  • Upload a file in the Upload sample and confirm both a Storage object and a sample_uploads row exist.
  • Run supabase functions list --project-ref <ref> and confirm deployed functions appear.
  • Re-run pnpm gen:types after schema edits and commit the updated types/database.ts.

On this page