Skip to content

Redesign the signup page as a split-screen brand moment - #21

Merged
1 commit merged into
mainfrom
feature_signup_page_redesign
Sep 7, 2026
Merged

1 commit merged into
mainfrom
feature_signup_page_redesign

Conversation

@Badri-Rajendran

Copy link
Copy Markdown
Owner

Problem

/register was a bare centered form on ivory, shared with /login, with zero brand presence — the product's actual front door (no marketing route exists) looked identical to every other unauthenticated screen. Two real functional gaps came with it, not just visual flatness:

  • No password visibility toggle anywhere in the app.
  • A duplicate-email signup showed a generic "check your details" message, because the backend never gave that specific case a distinct error code — dead-code fallback text in the form was never reachable.

Implementation

  • Split-screen layout (form left, brand panel right, stacking below 768px) via a new split variant on the existing AuthLayout — /login is untouched, still the plain centered column.
  • SignupBrandPanel: a deliberate one-time reversal of the app's normal ink-on-paper (uses --color-text/--color-surface directly, so it still reads as a reversal in dark mode rather than flattening into it), the serif "Trueup" wordmark on its first public-page appearance, real grounded copy (four model portfolios, monthly rebalancing) instead of generic fintech copy, and the genuine three-step sequence — create account, verify identity, link bank — numbered because it actually is one, with the current step marked via the design system's own sanctioned "current selection" use of the accent color.
  • Password visibility toggle, via a new optional labelExtra slot on the shared Input component (purely additive — every other caller unaffected, verified by screenshot).
  • Segmented password-strength meter driven by the exact same describePassword() the checklist already used — no new fabricated scale — as the page's one deliberate interactive/animated moment, respecting the app's existing global reduced-motion rule.
  • Backend fix: duplicate email now raises ValidationError(..., code="email_taken") instead of the shared validation_failed code, so the form shows "This account already exists — log in instead." with a working link.

Deliberately not added: a Terms-of-Service checkbox (no such page/legal content exists yet in the app — would mean inventing legal copy) and any specific regulatory disclosure claims (kept the one trust line to something true by construction).

Validation

  • Backend: tests/api/test_auth.py 24/24 pass, including the updated duplicate-email assertion.
  • npm run lint and npm run build clean.
  • Full manual pass in the browser against the running local backend: real registration end to end, the duplicate-email path with the new message and link, password toggle and strength meter both interactive, light and dark themes (dark mode's inversion explicitly checked), mobile width (375px), and a regression screenshot confirming /login — which doesn't use the new labelExtra prop — is pixel-identical to before.

Security / DB / API impact

  • Security: none. No new data collected, no new attack surface — the duplicate-email fix only makes an existing 422 response's code field more specific.
  • DB: none.
  • API: POST /auth/register's duplicate-email response gains a distinct code (email_taken instead of validation_failed); the response shape and status (422) are unchanged.

🤖 Generated with Claude Code

/register was a bare centered form on ivory, shared with /login, with
zero brand presence -- the product's actual front door (no marketing
route exists) looked identical to every other unauthenticated screen.

Adds:
- A split-screen layout (form left, brand panel right, stacking below
  768px) via a new `split` variant on the existing AuthLayout -- /login
  is untouched, still the plain centered column.
- SignupBrandPanel: a deliberate one-time reversal of the app's normal
  ink-on-paper (uses --color-text/--color-surface directly, so it still
  reads as a reversal in dark mode rather than flattening into it), the
  serif "Trueup" wordmark on its first public-page appearance, real
  grounded copy (four model portfolios, monthly rebalancing) instead of
  generic fintech copy, and the genuine three-step sequence -- create
  account, verify identity, link bank -- numbered because it actually is
  one, with the current step marked via the system's sanctioned
  "current selection" use of the accent color.
- A password visibility toggle, via a new optional `labelExtra` slot on
  the shared Input component (purely additive -- every other caller is
  unaffected, verified by screenshot).
- A segmented password-strength meter driven by the exact same
  describePassword() the checklist already used -- no new fabricated
  scale -- as the page's one deliberate interactive/animated moment,
  respecting the app's existing global reduced-motion rule.
- A real fix for the duplicate-email case: the backend now raises
  ValidationError(..., code="email_taken") instead of the shared
  validation_failed code, so the form can show "This account already
  exists -- log in instead." with a working link, instead of the
  generic "check your details" message the dead-code fallback string
  was silently never reaching.

Deliberately not added: a Terms-of-Service checkbox (no such page/legal
content exists yet in the app -- would mean inventing legal copy) and
any specific regulatory disclosure claims (kept the one trust line to
something true by construction).

Verified: backend 24/24 auth tests pass (including the updated
duplicate-email assertion); npm run lint and build clean; full manual
pass in the browser -- real registration through the running local
backend, the duplicate-email path end to end with the new message and
link, password toggle and strength meter both interactive, light and
dark themes (dark mode's inversion checked explicitly, panel correctly
flips light-on-dark), mobile width (375px, panel correctly hidden,
single column), and a regression screenshot confirming /login (which
doesn't use the new labelExtra prop) is pixel-identical to before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 7, 2026 00:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Badri-Rajendran Badri-Rajendran closed this pull request by merging all changes into main in 7f32337 Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants