@@ -51,6 +51,26 @@ export async function tryFinishWebOAuthSignIn(
5151 const client = getWebOAuthClient ( )
5252 const result = await client . init ( )
5353 if ( result ?. session ) {
54+ // A fresh signup (prompt=create) is created on the external PDS page, which
55+ // never runs our in-app signup wizard - so start onboarding here, the same
56+ // way that wizard does. Plain sign-ins carry no state and are untouched.
57+ //
58+ // Start it BEFORE login() so onboarding is already active the instant the
59+ // session appears. login() never touches onboarding state ('skip' only fires
60+ // on logout / account switch), and persisted onboarding defaults to 'Home'
61+ // (inactive) for a new account - so starting it AFTER login left a gap in
62+ // which the shell rendered the default home feed for ~1-2s before the wizard.
63+ //
64+ // We drive the in-memory onboarding reducer (startOnboarding) rather than
65+ // only writing persisted state. OnboardingProvider is mounted above the
66+ // session, so login() never remounts it, and on web persisted.write() does
67+ // not fire onUpdate listeners in the same tab (its cross-tab BroadcastChannel
68+ // never echoes back to the sender). A bare write would leave the onboarding
69+ // context stale and the wizard would not appear until a manual reload. The
70+ // reducer's 'start' action persists the step itself.
71+ if ( result . state === OAUTH_SIGNUP_STATE ) {
72+ startOnboarding ( )
73+ }
5474 // For a handle step-up the DID is unchanged, so login() replaces the
5575 // existing session in place with the upgraded (identity:handle) tokens.
5676 await login (
@@ -62,20 +82,6 @@ export async function tryFinishWebOAuthSignIn(
6282 } ,
6383 'LoginForm' ,
6484 )
65- // A fresh signup (prompt=create) is created on the external PDS page, which
66- // never runs our in-app signup wizard - so start onboarding here, the same
67- // way that wizard does. Plain sign-ins carry no state and are untouched.
68- //
69- // We drive the in-memory onboarding reducer (startOnboarding) rather than
70- // only writing persisted state. OnboardingProvider is mounted above the
71- // session, so login() never remounts it, and on web persisted.write() does
72- // not fire onUpdate listeners in the same tab (its cross-tab
73- // BroadcastChannel never echoes back to the sender). A bare write would
74- // leave the onboarding context stale and the wizard would not appear until
75- // a manual reload. The reducer's 'start' action persists the step itself.
76- if ( result . state === OAUTH_SIGNUP_STATE ) {
77- startOnboarding ( )
78- }
7985 if ( result . state === OAUTH_HANDLE_STEPUP_STATE ) {
8086 // The redirect lands at the site root; rewrite the path before the
8187 // navigator reads it so web linking resolves to account settings, where
0 commit comments