Relationships
#1204 Collective invite emailed-link return path is dropped: /accept-invite sends ?returnUrl= but /login reads ?redirect=
Opened by keeb · 7/17/2026· Shipped 8/14/2026
The collective-invite accept flow loses the return destination for every auth method, so after signing in the invitee lands on /profile instead of back on the accept-invite page.
Root cause
routes/o/[slug]/accept-invite.tsx (line ~50) redirects an unauthenticated invitee to:
/login?returnUrl=<encoded accept-invite url>but routes/login.tsx (line ~27) only reads the redirect query param:
const rawRedirect = [HOST-1]("redirect");The param names don't match (returnUrl vs redirect), so the return URL is silently discarded. After login/signup the user is sent to the default /profile and never returns to /o/<slug>/accept-invite, so the InviteAcceptor island is never shown.
Impact
Even setting aside the OAuth-specific failure, the emailed-link path is broken for email/password too. (The server-side auto-claim added for #1186 makes this non-blocking — invites are now claimed on verified sign-in regardless — but the emailed link still doesn't deep-link back correctly, which is confusing UX.)
Fix direction
Align the param name: either have accept-invite.tsx emit ?redirect=, or have login.tsx read returnUrl. Also thread it through the new-user OAuth path (newUserCallbackURL in islands/SignInForm.tsx is hardcoded to /choose-username and drops the destination), and forward it out of /choose-username.
Found while triaging #1186.
Shipped
Click a lifecycle step above to view its details.
keeb commented 8/12/2026, 3:54:07 PM
Half of this is fixed; recording what remains so the scope is accurate.
Fixed — the param-name mismatch that was the root cause. routes/login.tsx:30 now reads returnUrl first and falls back to redirect:
const rawRedirect = url.searchParams.get("returnUrl") ??
url.searchParams.get("redirect");routes/o/[slug]/accept-invite.tsx:54 still emits ?returnUrl=, so the emailed link now deep-links back correctly for email/password and for an existing-account social sign-in.
Still open — the second half this issue named: the new-user OAuth path. newUserCallbackURL in islands/SignInForm.tsx is customised only for the CLI callback (cliCallback), never for redirect. At lines 293, 377, 451 and 523 it is initialised to a bare /choose-username and only rewritten when cliCallback is set:
let callbackURL = redirect ?? "/profile";
let newUserCallbackURL = "/choose-username"; // <- redirect never threadedSo an invitee who clicks the emailed link and signs up with a social provider still lands on /choose-username with the destination dropped, and never returns to the accept-invite page. Four call sites, one per provider.
Staying open, scoped to that.
Sign in to post a ripple.