About this journey
I’m a former embedded coder who left Lockheed in the mid-1990s and haven’t seriously coded since. Beyond reading about today’s platforms, I came into this project knowing nothing about React, Next.js, Firebase, Vercel, or modern web app infrastructure. My goal is to have ChatGPT handle 99% of the coding while I guide the design, test the app, and provide feedback. What you’re reading is a day-by-day journal of building “Squares” — a commercial-ready sports squares app — with AI as my development partner.
Day 7: Email-Link Auth that Actually Works + Safer Preview Testing on Vercel
Theme: untangling Firebase Email-Link auth on Vercel, aligning domains and env vars, and adding a guarded “dev login” for Preview so I can iterate without hitting quotas.
What broke (and why)
-
auth/unauthorized-continue-uri
: Magic links failed because my runtime app was pointed at the wrong Firebase project (env mismatch), even though the allowlisted domain looked right. -
Local
.env*
confusion: Repo had.env.local
,.env.staging
,.env.production
. Vercel uses its own Environment Variables; those files were misleading the build. -
Quota exceeded: Rapid testing hit
auth/quota-exceeded
, which pushed me to add a Preview-only bypass.
The fixes that stuck
1) Make the continue URL deterministic
- Build
continueUrl
fromNEXT_PUBLIC_AUTH_RETURN_BASE
(Preview useshttps://squares-staging.vercel.app
), falling back towindow.location.origin
. - Log runtime Firebase config (apiKey/projectId/authDomain) and the final continueUrl for instant visibility.
2) Use Vercel envs as the source of truth
- Verified Preview variables:
NEXT_PUBLIC_FIREBASE_API_KEY
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
NEXT_PUBLIC_FIREBASE_PROJECT_ID
NEXT_PUBLIC_AUTH_RETURN_BASE=https://squares-staging.vercel.app
- Moved local
.env*
files out of the app tree to avoid accidental use during builds.
3) Map the domain to the right environment
- Vercel → Project → Settings → Domains
Connected
squares-staging.vercel.app
to Preview (branchstaging
). Result: magic links that land on/auth
resolve in the same environment that sent them.
4) “Remember this device” and route after sign-in
- Set Firebase persistence to
browserLocalPersistence
so signed-in users skip auth on revisit. - Email-link completion reads
?role=manager|player
and routes accordingly. - If already signed in and not on a link-complete URL, route to the last chosen role.
5) Preview-only dev login (no email needed)
-
Client flag:
NEXT_PUBLIC_BYPASS_MAGIC_LINK=true
(Preview only). -
Server route:
/api/dev-login
issues a short-lived custom token via Firebase Admin only if:- A secret header matches
DEV_LOGIN_SECRET
, and - The request is from the Preview deployment.
- A secret header matches
- Production path is unchanged; the bypass is Preview-scoped and guarded.
Small but meaningful UX tweaks
-
Manager dashboard
- Added a Logout button next to Create New Square.
- Free tier status now: “Free tier • 1 square at a time until {Mon DD} • Active squares: N”
- Purchase panel starts collapsed; Free Tier activation appears inside the dialog (less “prototype,” more “product”).
What I learned (again)
- If the error says “domain not allowlisted,” verify the runtime Firebase project. Logging
apiKey/projectId/authDomain
beats guessing. - Vercel Preview vs Production is mostly domains + env vars. Map correctly, set envs correctly, and the rest gets pleasantly boring.
- Quotas are real. A guarded Preview bypass keeps velocity high without compromising production auth.
Reflections from Day 7
This was a classic “it’s configured… just not the way you think” day. Once I surfaced the runtime values and mapped the domain to Preview, Firebase Email-Link auth behaved. The guarded dev login let me iterate without poking the quota hornet’s nest. Bonus: a couple of small UI touches made the Manager dashboard feel like a product, not a demo.
✅ Next steps
-
Vibe-code the “Create New Square” flow
- Minimal form: matchup/title, grid size (5×5 / 10×10), start/end, visibility.
- Client validation + friendly errors.
- Firestore write (draft → active), with optimistic UI on create.
- Invite flow stub (paste emails now; deeper contact picker later).
- Preview-only safeguards (no billing), Prod path ready to integrate with purchasing.
Top comments (0)