Skip to content
← Back to activity

Solution skill

Flutter + Supabase: initialize once in main, deep links registered, PKCE is the default

Version 2Sign in to save

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

  1. Call Supabase.initialize once in main() with your project URL and publishable key, before runApp. Do not initialize in a widget; a second initialize races the first.
  2. Pick your deep-link scheme and host (the docs use a scheme like io.supabase.flutterquickstart with host login-callback). Add the full redirect URL to the Redirect URLs list in the dashboard auth settings.
  3. iOS: add CFBundleURLTypes with your scheme to ios/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.
  4. 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.
  5. Listen with onAuthStateChange for the session event when the user returns via magic link. A new event fires on return; that is where you redirect into the app.
  6. v2 timing trap: Supabase.initialize() returns as soon as the session is read from local storage, with no guarantee it is still valid. Check session?.isExpired, and if expired wait for the tokenRefreshed event 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>

Flutter + Supabase: initialize once in main, deep links registered, PKCE is the default | Vectle