fix(web): recover lost sign-ups on the register page

Merged
RI
3d ago
+229-27

Why

Funnel data since API sign-up went live (Oct 22): 85% of submitters end up with an account, but 40% hit an error first and 63 gave up. This PR fixes the front-end side of those errors. The leaked-password 500 is fixed in the backend PR (Cap-go/capgo).

SourceFinding
PostHog $exceptionTurnstile client errors (600010, 110600 timeout, 300010/300030) for about 30 people in 14 days. They were told to tick a box that never rendered.
PostHog website_signup_erroremail_exists / user_already_exists: 9 of 18 people left after a red toast
PostHog website_signup_errortransport: every case came from China, and 6 people never signed up
PostHog autocapture82 people clicked Pricing from /register, and 39 clicked the header sign-up button while already on the form

What changed

  • Turnstile recovery: success, error, expired and timeout callbacks. On error the widget resets itself up to twice and shows "retrying". After that it tells the visitor to turn off ad or privacy blockers. Each failure is captured as website_signup_error with stage: captcha and the Turnstile code.
  • Existing account: an inline notice with Sign in and Reset password links (console.capgo.app/forgot_password/) replaces the toast.
  • Network failure: the toast now asks people to check their connection or VPN and gives the support email.
  • API weak_password: focuses the password field and keeps the server's reason on screen for 8 seconds.
  • Price line: "Paid plans from {price}/mo, billed yearly, after the trial. See pricing". The amount is a live-price element (data-price-plan, year-monthly) filled in by src/scripts/currency.ts, so visitors see the Stripe price for their country and currency, regional Solo discount included, exactly as on /pricing. The HTML keeps the USD fallback ($12). It's hidden for direct-offer visitors (data-trial-copy), and the link opens in a new tab so the form stays.
  • Header: no "Start for free" button on /register itself (desktop and mobile). On mobile the Login button takes the full row.
  • Copy: new keys in all three copy files.

Checks

  • bun test src/scripts/register.test.ts src/services/registration.test.ts: 12 pass, including 3 new tests for the email-exists, network and API-weak-password paths.
  • astro check: 0 errors.
  • oxlint: no new warnings.
  • Rendered /register/ locally and confirmed the price line and the missing header button.

šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.