From f9f98b1a65c276140727a779d997ab0800fd71ba Mon Sep 17 00:00:00 2001
From: Michael Chihlas
Date: Fri, 15 May 2026 00:34:23 -0400
Subject: [PATCH] fix(routing): finish /home migration in WelcomeStep3 +
VerifyEmailPage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The original public-landing routing refactor migrated WelcomeRouter,
WelcomeStep1, and WelcomeStep2 post-onboarding redirects to /home, but
left four sites still pointing at the old / + query-string destinations:
- WelcomeStep3 `completeWizardAndExit` (Send invites)
- WelcomeStep3 `handleSkipStep` (Skip)
- VerifyEmailPage post-verify auto-redirect (`setTimeout`)
- VerifyEmailPage success-state "Go to dashboard" Link
These all worked by accident because PublicLanding redirects authed
users from / to /home — so users still landed on the dashboard, but
through an unnecessary mount-and-redirect flicker, and the
`?welcome=true` / `?verified=1` query markers got dropped on the way.
Drop both query markers — neither is read anywhere in the codebase
(grepped frontend/src; the dashboard's onboarding UX is driven by
`getOnboardingStatus`, not URL state). Carrying dead URL params
just invites future "is this load-bearing?" investigations.
Test stubs in WelcomeStep3.test.tsx and VerifyEmailPage.test.tsx
moved from `` to `` so the
assertions verify the new destination instead of accidentally matching
the old one (the previous stubs masked the partial migration).
Out of scope: AcceptInvitePage and OAuthCallbackPage still use
`?welcome=teammate`, but that one carries an explicit "decoded by the
dashboard in Task 41" annotation and may be wired up later, so left
untouched.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
frontend/src/pages/VerifyEmailPage.tsx | 10 ++++------
frontend/src/pages/__tests__/VerifyEmailPage.test.tsx | 6 +++---
frontend/src/pages/welcome/WelcomeStep3.tsx | 6 +++---
.../src/pages/welcome/__tests__/WelcomeStep3.test.tsx | 2 +-
4 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/frontend/src/pages/VerifyEmailPage.tsx b/frontend/src/pages/VerifyEmailPage.tsx
index 12fb49b8..0ac355a0 100644
--- a/frontend/src/pages/VerifyEmailPage.tsx
+++ b/frontend/src/pages/VerifyEmailPage.tsx
@@ -20,8 +20,7 @@ const SUCCESS_REDIRECT_MS = 1200
* "Already verified" state. No API call.
* - Else fire `POST /auth/email/verify` exactly once (a `useRef` guard keeps
* React 19 strict-mode double-invoke from double-firing the call). On
- * success, refresh the auth store and bounce to `/?verified=1` so the
- * dashboard surfaces a toast.
+ * success, refresh the auth store and bounce to `/home`.
* - On error, show "Invalid or expired token" + a "Resend" CTA that calls
* `POST /auth/email/send-verification`.
*/
@@ -70,10 +69,9 @@ export function VerifyEmailPage() {
if (cancelled) return
setStatus('success')
toast.success('Email verified')
- // Brief success state, then redirect with a query flag so the
- // dashboard can re-surface confirmation if it wants to.
+ // Brief success state, then redirect to the dashboard.
window.setTimeout(() => {
- navigate('/?verified=1', { replace: true })
+ navigate('/home', { replace: true })
}, SUCCESS_REDIRECT_MS)
})
.catch((err) => {
@@ -126,7 +124,7 @@ export function VerifyEmailPage() {
Redirecting you to the dashboard…
} />
- dashboard} />
+ dashboard} />
,
@@ -130,7 +130,7 @@ describe('VerifyEmailPage', () => {
} />
- dashboard} />
+ dashboard} />
,
@@ -142,7 +142,7 @@ describe('VerifyEmailPage', () => {
} />
- dashboard} />
+ dashboard} />
,
diff --git a/frontend/src/pages/welcome/WelcomeStep3.tsx b/frontend/src/pages/welcome/WelcomeStep3.tsx
index b345dfa3..be2f6309 100644
--- a/frontend/src/pages/welcome/WelcomeStep3.tsx
+++ b/frontend/src/pages/welcome/WelcomeStep3.tsx
@@ -39,7 +39,7 @@ function makeEmptyRow(): InviteRow {
*
* 1. POST `/accounts/me/invites/bulk` with populated rows.
* 2. PATCH `/users/me/onboarding-step` `{step: 3, action: "complete"}`.
- * 3. Navigate to `/?welcome=true` and fire a "You're all set" toast.
+ * 3. Navigate to `/home` and fire a "You're all set" toast.
*
* Partial-failure UX: rows in `failed[]` keep their input and show an
* inline error. The wizard does NOT auto-advance when there are failures —
@@ -109,7 +109,7 @@ export function WelcomeStep3() {
await onboardingApi.updateStep({ step: 3, action: 'complete' })
await fetchUser()
toast.success("You're all set!")
- navigate('/?welcome=true')
+ navigate('/home')
}
const handleSendInvites = async () => {
@@ -177,7 +177,7 @@ export function WelcomeStep3() {
await onboardingApi.updateStep({ step: 3, action: 'skip' })
await fetchUser()
toast.success("You're all set!")
- navigate('/?welcome=true')
+ navigate('/home')
} catch {
setError('Could not save. Please try again.')
setSubmitting(null)
diff --git a/frontend/src/pages/welcome/__tests__/WelcomeStep3.test.tsx b/frontend/src/pages/welcome/__tests__/WelcomeStep3.test.tsx
index c90be2dd..b6d0788e 100644
--- a/frontend/src/pages/welcome/__tests__/WelcomeStep3.test.tsx
+++ b/frontend/src/pages/welcome/__tests__/WelcomeStep3.test.tsx
@@ -88,7 +88,7 @@ function renderPage() {
} />
- dashboard} />
+ dashboard} />
,
)