SETUP.md — OAuth & Environment Setup
This is the step-by-step for every external service this project depends on.
Update this document whenever you hit a snag — the goal is that future-you
(or someone else picking this up) can stand the project up cold.
Table of contents
- Environment variables
- Supabase project
- Google OAuth
- Microsoft / Azure OAuth
- Apple OAuth
- Email magic link
- Netlify deployment
Environment variables
Copy .env.local.example → .env.local and fill in:
| Variable |
Where to find it |
Notes |
NEXT_PUBLIC_SUPABASE_URL |
Supabase → Settings → API → Project URL |
Public — bundled into client |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
Supabase → Settings → API → anon / publishable key |
Public — bundled into client |
SUPABASE_SERVICE_ROLE_KEY |
Supabase → Settings → API → service_role key |
SECRET. Server only. Never commit. |
NEXT_PUBLIC_SITE_URL |
Your site URL |
http://localhost:3000 for dev, real URL in prod |
For Netlify, set these in Site Settings → Environment variables — not in
.env.local (that file isn’t deployed).
Supabase project
Already created: project-heirloom in East US (N. Virginia).
Auth settings to verify
In the Supabase dashboard, go to Authentication → URL Configuration:
- Site URL:
http://localhost:3000 for dev. Update to your real URL in prod.
- Redirect URLs: add all of these (one per line):
http://localhost:3000/auth/callback
https://<your-netlify-subdomain>.netlify.app/auth/callback
https://<your-real-domain>/auth/callback (when applicable)
Without the redirect URL listed here, OAuth will fail with redirect_uri_mismatch
even if the upstream provider is configured correctly. This is the #1 source
of OAuth bugs.
Apply the schema
# Option A: paste supabase/migrations/0001_initial_schema.sql into the SQL editor
# Option B: use the Supabase CLI
supabase db push
Verify after applying:
- Database → Tables shows
profiles, families, family_members
- Each table has the RLS shield icon
- Database → Functions shows
handle_new_user, is_family_member, tg_set_updated_at
- Database → Triggers shows
on_auth_user_created on auth.users
Google OAuth
1. Google Cloud Console setup
- Go to https://console.cloud.google.com/.
- Create a new project:
project-heirloom (or use an existing Kane PC project).
- APIs & Services → OAuth consent screen:
- User type: External
- App name:
Project Heirloom (placeholder — change when name is final)
- User support email: your Kane PC email
- Developer contact: your Kane PC email
- Scopes: add
email, profile, openid (default)
- Save and continue. While in dev, the app stays in “Testing” mode.
- Add yourself and your wife as test users so you can both sign in.
- APIs & Services → Credentials → Create Credentials → OAuth client ID:
- Click Create. Save the Client ID and Client secret.
2. Supabase configuration
- Supabase dashboard → Authentication → Providers → Google
- Toggle Enable.
- Paste the Client ID and Client secret from step 4 above.
- Save.
3. Test
npm run dev, open http://localhost:3000/login
- Click “Continue with Google” — should bounce through Google → Supabase → back to
/home.
Microsoft / Azure OAuth
Microsoft is the one that bit us. Document anything weird here so we don’t
repeat it.
1. Azure App Registration
- Go to https://portal.azure.com/ → Microsoft Entra ID (formerly Azure AD).
- App registrations → New registration:
- Name:
project-heirloom
- Supported account types: “Accounts in any organizational directory and personal Microsoft accounts” (this is the multi-tenant + consumer option — critical for letting personal Outlook/Hotmail accounts in)
- Redirect URI:
- Platform: Web
- URI:
https://equhvafcswisxrbyjtit.supabase.co/auth/v1/callback
- Register.
- Copy the Application (client) ID — you’ll need it.
2. Create a client secret
- Certificates & secrets → Client secrets → New client secret
- Description:
project-heirloom-supabase
- Expires: 24 months (set a calendar reminder to rotate before expiry, or auth will silently break)
- Add — copy the Value column immediately. The portal only shows it once.
3. API permissions
- API permissions → Add a permission → Microsoft Graph → Delegated permissions
- Add:
email, openid, profile, User.Read
- Grant admin consent if prompted (only relevant for work accounts).
4. Token configuration (so Supabase gets the email)
- Token configuration → Add optional claim
- Token type: ID
- Check
email and upn
- Add. If asked about Microsoft Graph permissions, agree.
Without this, OAuth succeeds but Supabase has no email for the user, which
breaks profile creation.
5. Supabase configuration
- Supabase dashboard → Authentication → Providers → Azure
- Toggle Enable.
- Azure Tenant ID:
common
common = both work and personal accounts
consumers = personal only (Outlook/Hotmail)
organizations = work only
- We want
common.
- Azure Client ID: the Application (client) ID from step 1.3
- Azure Secret: the Value from step 2.4
- Save.
Known gotchas
- “AADSTS50011: redirect URI does not match” — the redirect URI in Azure
must match Supabase’s callback URL character-for-character, including
trailing slashes (or lack thereof). It is
https://equhvafcswisxrbyjtit.supabase.co/auth/v1/callback.
- “Need admin approval” when signing in with a work account — the user’s
org has admin-consent-required mode on. They need to ask their IT admin to
approve, or sign in with a personal account instead.
- No email returned — go back to step 4 (token configuration). Most common
cause of “user signed in but profile is broken.”
Apple OAuth
Apple is the most painful of the three. Budget an hour the first time.
Prerequisites
You need a paid Apple Developer Program membership ($99/year). If Kane PC
already has one, use that team.
1. Create an App ID
- https://developer.apple.com/account/resources/identifiers/list
- + → App IDs → App → Continue
- Description:
Project Heirloom
- Bundle ID: explicit, e.g.
com.kanepc.projectheirloom
- Capabilities: check Sign in with Apple
- Continue → Register
2. Create a Services ID (this is what’s used for web sign-in)
- + → Services IDs → Continue
- Description:
Project Heirloom Web
- Identifier:
com.kanepc.projectheirloom.web (must be different from the App ID)
- Continue → Register
- Click into the new Services ID → check Sign in with Apple → Configure:
- Primary App ID: select the App ID from step 1
- Domains and Subdomains:
equhvafcswisxrbyjtit.supabase.co
- Return URLs:
https://equhvafcswisxrbyjtit.supabase.co/auth/v1/callback
- Save → Continue → Save
3. Create a Sign in with Apple key
- https://developer.apple.com/account/resources/authkeys/list
- + → Key Name:
project-heirloom-signin
- Check Sign in with Apple → Configure → Primary App ID: select your App ID
- Save → Continue → Register
- Download the .p8 key file immediately. You can only download it once.
Save it somewhere safe in 1Password/Bitwarden.
- Note the Key ID (10 chars) and your Team ID (top-right of the
developer portal).
4. Generate the client secret JWT
Apple doesn’t give you a client secret directly — you generate a JWT signed
with the .p8 key. Supabase has a tool for this:
The JWT expires after 6 months max — set a calendar reminder.
5. Supabase configuration
- Supabase dashboard → Authentication → Providers → Apple
- Toggle Enable.
- Services ID:
com.kanepc.projectheirloom.web (from step 2)
- Secret Key (for OAuth): the JWT generated in step 4
- Save.
Known gotchas
- Apple only gives you the user’s name on first sign-in. Cache it. If
you miss it, the user has to revoke and re-grant access from their Apple
account settings to get it back.
- Apple email is often a relay address (
@privaterelay.appleid.com). Don’t
send marketing email to these — they’ll bounce or be filtered.
Email magic link
Already works out of the box with Supabase. No config needed for dev.
For production:
- Supabase’s free tier sends from a generic address with low deliverability.
- Before launch: configure custom SMTP in Authentication → Settings → SMTP Settings.
Recommended: Resend, Postmark, or SendGrid.
- Customize the email template in Authentication → Email Templates → Magic Link.
Netlify deployment
- https://app.netlify.com/ → Add new site → Import from Git
- Connect to GitHub, select
KANEPC23/project-heirloom
- Build settings:
- Build command:
npm run build
- Publish directory:
.next
- Netlify auto-detects Next.js and adjusts.
- Site Settings → Environment variables — add the same vars from
.env.local:
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
SUPABASE_SERVICE_ROLE_KEY
NEXT_PUBLIC_SITE_URL — set to your Netlify URL (e.g. https://project-heirloom.netlify.app)
- Deploy.
- After first deploy succeeds:
- Update Supabase Authentication → URL Configuration → Site URL and Redirect URLs to include the Netlify URL
- Update Google OAuth, Azure, and Apple to also accept the Netlify URL as a redirect