Bug: /verify?fromSignup=true is a dead-end without signup context; signup OTP flow is broken
Summary
The email verification page assumes the user always arrives from register/login in the same tab. Direct navigation (bookmark, pasted URL, new tab) renders an OTP form with no email and no recovery path. Separately, the post-signup OTP path never sends a code on load and verifies with the wrong Better Auth API.
Environment
bun install in repo root
- Copy
.env.example → .env; set DATABASE_URL, run bunx drizzle-kit push
- Set
EMAIL_PROVIDER=log (OTP prints in dev server terminal)
- For full signup enforcement, set
EMAIL_VERIFICATION_ENABLED=true (see note below on env parsing)
bun dev → http://localhost:3000
Steps to reproduce
A) Cold visit (no redirect)
- Open a new tab / incognito window
- Go to
http://localhost:3000/verify?fromSignup=true
- Wait a few seconds
Actual: Page stays on /verify, shows “Verify Your Email” and “sent to your email”, empty OTP inputs, disabled Verify button.
Expected: Redirect to /register (or /login) when there is no pending verification email in sessionStorage and no unverified session email.
B) Signup OTP never auto-sends
- Register at
/register with a new email
- Land on
/verify?fromSignup=true without clicking Resend
Actual: No OTP is sent. use-verification.ts only flips isSendingInitialOtp and never calls sendVerificationOtp.
Expected: OTP sent automatically using type email-verification.
C) Wrong verify API after signup
- Complete signup, click Resend on
/verify?fromSignup=true
- Enter the OTP from terminal / DB (
email-verification-otp-* vs sign-in-otp-*)
Actual: verifyCode() always calls client.signIn.emailOtp. Signup sends email-verification OTPs, which require client.emailOtp.verifyEmail.
Expected: When fromSignup=true, call emailOtp.verifyEmail; otherwise signIn.emailOtp.
Root cause
- Verify page has no guard when
sessionStorage.verificationEmail is missing
- Initial OTP send effect was never implemented (only a flag)
- Resend hardcodes OTP type
sign-in regardless of fromSignup
- “Back to signup” links to
/signup but ShipFree route is /register
Suggested fix
See PR branch fix/verify-page-guards:
- Redirect to
/register when verification context is missing (client) and to /dashboard when already verified (server)
- Send OTP on load with correct type from
fromSignup query param
- Use
emailOtp.verifyEmail for signup verification
- Fix back link to
/register
Manual verification (after fix)
- Cold
/verify?fromSignup=true → redirects to /register
- Register →
/verify shows your email, OTP auto-sent (terminal log)
- Enter OTP → redirects to
/dashboard with verified session
Bug:
/verify?fromSignup=trueis a dead-end without signup context; signup OTP flow is brokenSummary
The email verification page assumes the user always arrives from register/login in the same tab. Direct navigation (bookmark, pasted URL, new tab) renders an OTP form with no email and no recovery path. Separately, the post-signup OTP path never sends a code on load and verifies with the wrong Better Auth API.
Environment
bun installin repo root.env.example→.env; setDATABASE_URL, runbunx drizzle-kit pushEMAIL_PROVIDER=log(OTP prints in dev server terminal)EMAIL_VERIFICATION_ENABLED=true(see note below on env parsing)bun dev→ http://localhost:3000Steps to reproduce
A) Cold visit (no redirect)
http://localhost:3000/verify?fromSignup=trueActual: Page stays on
/verify, shows “Verify Your Email” and “sent to your email”, empty OTP inputs, disabled Verify button.Expected: Redirect to
/register(or/login) when there is no pending verification email insessionStorageand no unverified session email.B) Signup OTP never auto-sends
/registerwith a new email/verify?fromSignup=truewithout clicking ResendActual: No OTP is sent.
use-verification.tsonly flipsisSendingInitialOtpand never callssendVerificationOtp.Expected: OTP sent automatically using type
email-verification.C) Wrong verify API after signup
/verify?fromSignup=trueemail-verification-otp-*vssign-in-otp-*)Actual:
verifyCode()always callsclient.signIn.emailOtp. Signup sendsemail-verificationOTPs, which requireclient.emailOtp.verifyEmail.Expected: When
fromSignup=true, callemailOtp.verifyEmail; otherwisesignIn.emailOtp.Root cause
sessionStorage.verificationEmailis missingsign-inregardless offromSignup/signupbut ShipFree route is/registerSuggested fix
See PR branch
fix/verify-page-guards:/registerwhen verification context is missing (client) and to/dashboardwhen already verified (server)fromSignupquery paramemailOtp.verifyEmailfor signup verification/registerManual verification (after fix)
/verify?fromSignup=true→ redirects to/register/verifyshows your email, OTP auto-sent (terminal log)/dashboardwith verified session