Commit2aefa37
fix(signin): restore password login form alongside OAuth buttons
fix(signin): restore password login form alongside OAuth buttons The signin-v2 redesign shipped passwordless (OAuth + passkey + magic-link only) with no username/password field; its subheading even said no new passwords. Deploying it as-is would REMOVE password login from the live site, locking out any user whose only working method is a password (and whose Google/GitHub/email may not be configured). Root cause of the owner lockout. Restore a real form (method=post, action=/login) with username + password + Sign in, plus a Forgot password link (/forgot-password), placed above the Google/GitHub/passkey/magic options. POST /login already exists and works, and CSRF is skipped for sessionless requests, so no token field is needed. Net result: three independent ways in (password, Google, GitHub) as the owner asked. Verified: /login renders 200 with password + username fields, form posts to /login, Google + GitHub buttons present, forgot link present. web-routes 13/13. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 file changed+68−42aefa37b832d26fc10a7801f35af5b4bfbc77767
1 changed file+68−4
Modifiedsrc/views/signin-v2.tsx+68−4View fileUnifiedSplit
@@ -23,15 +23,46 @@ export const SignInV2: FC<SignInV2Props> = (props) => {
2323
2424 <div class="si-form-wrap">
2525 <h1 class="si-heading">Sign in</h1>
26 <p class="si-subheading">Use the identity you already have — no new passwords.</p>
26 <p class="si-subheading">Sign in with your password, or a connected provider.</p>
2727
2828 {error && (
2929 <div class="si-error-banner">{error}</div>
3030 )}
3131
32 {redirect && (
33 <input type="hidden" name="redirect" value={redirect} />
34 )}
32 <form
33 class="si-login-form"
34 method="post"
35 action={redirect ? `/login?redirect=${encodeURIComponent(redirect)}` : "/login"}
36 >
37 <label class="si-field-label" for="si-username">Username or email</label>
38 <input
39 id="si-username"
40 class="si-email-input"
41 type="text"
42 name="username"
43 autocomplete="username"
44 placeholder="ccantynz or you@example.com"
45 required
46 />
47 <label class="si-field-label" for="si-password">Password</label>
48 <input
49 id="si-password"
50 class="si-email-input"
51 type="password"
52 name="password"
53 autocomplete="current-password"
54 placeholder="Your password"
55 required
56 />
57 <button type="submit" class="si-btn si-btn-github si-submit">Sign in</button>
58 <a href="/forgot-password" class="si-forgot">Forgot password?</a>
59 </form>
60
61 <div class="si-divider">
62 <span class="si-divider-line"></span>
63 <span class="si-divider-label">OR</span>
64 <span class="si-divider-line"></span>
65 </div>
3566
3667 <div class="si-oauth-group">
3768 <a href="/login/github" class="si-btn si-btn-github">
@@ -321,6 +352,39 @@ const css = `
321352 margin-bottom: 18px;
322353}
323354
355/* ── Password form ── */
356
357.si-login-form {
358 display: flex;
359 flex-direction: column;
360 margin: 0 0 4px;
361}
362
363.si-field-label {
364 font-size: 12.5px;
365 font-weight: 600;
366 color: #3a3d47;
367 margin: 10px 0 5px;
368}
369
370.si-submit {
371 width: 100%;
372 margin-top: 16px;
373 border: 0;
374}
375
376.si-forgot {
377 font-size: 12.5px;
378 color: #6b7080;
379 text-decoration: none;
380 margin-top: 12px;
381 align-self: flex-start;
382}
383
384.si-forgot:hover {
385 color: #4353c9;
386}
387
324388/* ── OAuth buttons ── */
325389
326390.si-oauth-group {
327391