Isaac Hess
Back to Isaac Hess

Provider setup

Every provider in order, the environment variables each needs, where each key comes from, and the gotcha that costs you a session.

Per provider: what it gives you, the env vars, where each key comes from, and the gotcha that costs a session.


Supabase — database, auth, storage

VarSecretWhere
NEXT_PUBLIC_SUPABASE_URLnoProject Settings → API
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYyessame page
SUPABASE_SECRET_KEYcriticalsame page — service role, bypasses RLS

Set up first: everything downstream references the project ref.

Gotchas. The service key bypasses RLS entirely — treat it as a root password and confine it to server-only directories. Migration tooling that stamps its own timestamps instead of your committed filename will desync the migration ledger from your repo; apply a committed migration under its own version. Free-tier projects pause when idle, which reads as an outage.


Vercel — hosting

VarSecretWhere
BLOB_READ_WRITE_TOKENyesStorage → Blob (only if using blob storage)
CRON_SECRETyesyou generate it; guards cron routes

Gotchas. Never deploy from the CLI in an unlinked directory — it creates a stray project named after the folder and bills failed builds. Vars marked Sensitive are write-only: env pull returns them as empty strings, and the dashboard's masked placeholder is not the stored value. To fix a suspect value, overwrite it; never ask anyone to read it back. An env change only takes effect on a new deployment — a browser refresh does nothing.


Resend — transactional email

VarSecretWhere
RESEND_API_KEYyesAPI Keys
RESEND_FROMnoyour verified sender

Scope matters: if the code touches contacts or broadcasts, sending_access is not enough — it needs full_access.

Gotchas. An invalid key returns 400 "API key is invalid", not 401 — easy to misread as a wrong endpoint. Domain verification needs DNS records and is not instant; start it early. Send from a subdomain so marketing volume cannot damage the root domain's reputation.


Stripe Connect — payments and payouts

VarSecretWhere
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYnoDevelopers → API keys
STRIPE_SECRET_KEYcriticalsame page
STRIPE_WEBHOOK_SECRETyesper webhook endpoint
STRIPE_WEBHOOK_SECRET_CONNECTyesConnect events use a separate endpoint and secret

Gotchas. Connect events are a distinct endpoint with a distinct secret — missing that means silently unprocessed account events. Test and live keys are separate universes; a valid test key in a production slot returns 200 and is still wrong, so assert the prefix, not just the status. Never release a payout before the cancellation window closes.


Twilio — SMS

VarSecretWhere
TWILIO_ACCOUNT_SIDyesConsole → Keys & Credentials, Live column
TWILIO_AUTH_TOKENyessame
TWILIO_MESSAGING_SERVICE_SIDyesMessaging → Services
TWILIO_FROM_NUMBERusually leave empty; see below

Start A2P 10DLC registration on day one. Brand registration, campaign vetting, and per-campaign monthly fees, with approval measured in days to weeks.

Gotchas, all three of which we hit.

  • Twilio shows Live and Test credentials side by side and it is easy to paste the Test pair. Test credentials return 403 code 20008 on every real resource, so SMS looks configured and silently does nothing.
  • A messaging service with no phone number attached fails to send even with valid credentials. Accounts accumulate near-identically-named services — verify which one actually holds the number.
  • If the sending code prefers From over MessagingServiceSid, setting a from number bypasses your verified A2P campaign and routes over a bare long code, inviting carrier filtering. Leave it empty and send through the service.
  • Prove production works by listing recent messages; delivered messages are the only conclusive evidence.

Google Maps

VarSecretWhere
NEXT_PUBLIC_GOOGLE_MAPS_API_KEYyesCloud Console → Credentials (browser key, referrer-restricted)
GOOGLE_MAPS_API_KEYyesseparate server key, IP-restricted

Gotchas. These must be two different keys with different restrictions. A referrer-restricted browser key fails server-side with "API keys with referer restrictions cannot be used with this API" — that is the key being wrong for the call, so read error_message before concluding it is dead. Probe the API the key is actually scoped for. Attribution and logo display are terms-of-service requirements, not styling choices. See costs.md before writing any call.


Sentry and PostHog

VarSecretNotes
NEXT_PUBLIC_SENTRY_DSNnosafe to expose
SENTRY_AUTH_TOKENyesbuild-time only — sourcemap upload; empty locally is correct
NEXT_PUBLIC_POSTHOG_KEYnoclient key

Add last. Neither blocks anything.


Webhook signing secrets

SEND_EMAIL_HOOK_SECRET, RESEND_EVENTS_WEBHOOK_SECRET, and similar verify inbound requests. Nothing calls localhost, so empty locally is correct — they only matter in deployed environments. Do not treat them as missing configuration; a doctor that flags them as broken trains people to ignore it.