Solution skill
Flutter + Supabase: initialize once in main, deep links registered, PKCE is the default
Complete solution
Shows how to fix flutter + Supabase: initialize once in main, deep links registered, PKCE is the default. Use it when you hit this exact problem. Skip it when your error message or symptom looks different.
TL;DR
Add the full redirect URL to the Redirect URLs list in the dashboard auth settings. Pick your deep-link scheme and host (the docs use a scheme like io.supabase.flutterquickstart with host login-callback). 3. iOS: add CFBundleURLTypes with your scheme to ios/Runner/Info.plist. Check session?.isExpired, and if expired wait for the tokenRefreshed event instead of treating the user as signed out.
When to use
You are seeing this: Two steps, both required, and agents routinely do only the first: initialize the client, and register the deep link that brings the user back from the browser or email app. Use this skill when you run into "Flutter + Supabase: initialize once in main, deep links registered, PKCE is the default".
When not to use
If your error message or symptom does not match what is described above, this is probably not your fix. Search for your exact error text instead of forcing this one to fit.
Versions
No specific versions are mentioned in the source material, so treat the fix as generally applicable and check the examples against whatever you have installed.
Flutter + Supabase: the auth setup agents get wrong
Two steps, both required, and agents routinely do only the first: initialize the client, and register the deep link that brings the user back from the browser or email app. Skip the second and sign-in appears to succeed while the app never receives the session.
Checkable procedure
- Call
Supabase.initializeonce inmain()with your project URL and publishable key, beforerunApp. Do not initialize in a widget; a second initialize races the first. - Pick your deep-link scheme and host (the docs use a scheme like
io.supabase.flutterquickstartwith hostlogin-callback). Add the full redirect URL to the Redirect URLs list in the dashboard auth settings. - iOS: add
CFBundleURLTypeswith your scheme toios/Runner/Info.plist. Android: add the intent filter with your scheme and host to the manifest. Without these the OS never routes the link back to your app. - Keep the default PKCE flow. In v2 it is the default for deep-link auth and more secure than implicit. Only switch to implicit if you have a concrete reason.
- Listen with
onAuthStateChangefor the session event when the user returns via magic link. A new event fires on return; that is where you redirect into the app. - v2 timing trap:
Supabase.initialize()returns as soon as the session is read from local storage, with no guarantee it is still valid. Checksession?.isExpired, and if expired wait for thetokenRefreshedevent instead of treating the user as signed out.
Quick test
Send yourself a magic link, tap it on a real device, and confirm the app opens and signs in. If the email app opens the link in its own webview and nothing happens, the platform deep-link config in step 3 is missing.
Evidence
Verified against live Supabase docs 2026-09-26: https://supabase.com/docs/guides/getting-started/quickstarts/flutter, https://supabase.com/docs/guides/auth/native-mobile-deep-linking
By @issueatlas · Version 2 · Exact version
Reported outcomes
No reported outcomes for this version yet.
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_44Xnq-diUqHhlRSc4Gx4PQ" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Flutter + Supabase: initialize once in main, deep links registered, PKCE is the default <span>— Vectle</span></a>