Test your signup flow before launch

Five things that break signup flows, ranked by how often they show up, with a 60-second audit that walks the flow end-to-end.

Your signup flow is the highest-stakes test you’ll ever run — the real user’s first thirty seconds — and the entire free-audit incumbent class (IsMyWebsiteReady and friends) doesn’t test it. They check sitemap, robots.txt, SSL, speed, OG tags. None of them walks a flow. “Does my signup flow actually work before launch” is the question nobody serves, and it’s the question that costs launches. In a June 2026 audit of 49 fresh web launches, 38 (78%) shipped with at least one critical verified finding on day one; the community repeatedly names the signup flow as the single highest-impact place for those failures to land.

Why static checkers miss this

Static audits read your pages without using them. They confirm the page exists, returns 200, has the right meta tags. They do not click a button, fill a form, watch for a redirect, or read the cookie the server sets. Functional-flow testing is a different problem. The good news: it’s a small, bounded problem. The signup flow is two or three screens. Five to seven things break it. You can know all of them.

The five things that break signup flows

The community — r/vibecoding, r/nocode, the Beesoul 9-failure-mode list, multiple Indie Hackers threads — names the same failure modes over and over. In order of how often they show up in founder reports, they are:

  1. Email verification breaks silently. The user submits the form. The success page renders. The user is in your database. The verification email goes to spam or never arrives at all. The user is locked out of their own account and has no idea why. Why vibe coding causes it: DMARC/SPF/DKIM is not configured; the consent banner blocks the initial transactional send; the LLM hallucinates an email-send library that doesn’t actually work in production. The Prufa check that catches it: the flows analyzer exercises the flow spec — the LLM detects the form submit and the success page; plain code re-verifies the entry selector in the DOM. 5-minute manual check: test signup with a fresh email address. Read the inbox. If the verification email is in spam, the bug is in your DNS records; if it’s not there at all, the bug is in your send code.

  2. The success redirect updates UI but the server-side state never updates. The user lands on the dashboard. The UI says “Welcome, Acme Co.” The auth cookie never set. The session row never created. The user refreshes. It works. For them. The next user hits the same race and bounces. Why vibe coding causes it: the LLM wires the post-signup flow to the client-side redirect (the URL the browser lands on after the form posts), not to the webhook from the auth provider. Same class of failure as a payment webhook that silently drops events. The Prufa check: the CaptureMeta record captures the cookies set during the flow, the response headers of the success page, and the network requests. If the success page returns 200 but no auth cookie is set, the finding is verified. 5-minute manual check: in DevTools, open Application → Cookies after signup. Look for a session cookie. If there isn’t one, you have this bug.

  3. The form posts to the wrong endpoint. Two /signup URLs exist in the codebase — one in the LLM’s training data, one in the new app. The form posts to the old one. The old endpoint returns 200 with a different response shape. The signup looks like it worked; the user is in limbo. Why vibe coding causes it: the LLM generated the form, then generated the route handler separately, and they drifted. The Prufa check: the flows analyzer matches the form’s action URL to the routes it discovered by walking the entry page. A mismatch is a verified warning. 5-minute manual check: in DevTools → Network, watch the form submit. Read the request URL and the response status. If the URL is not what you expect, or the response is 200 but the body is empty, you have this bug.

  4. Password validation rejects valid passwords. The LLM set a min-length of 12 + special-character requirement. The founder tested with their own 16-character password and it worked. Real users with 8-character passwords are silently rejected, or — worse — accepted by the form, then the server returns 422 and the UI shows a generic “Something went wrong.” Why vibe coding causes it: the LLM’s training set includes strong-password guidance; the founder never thought to test with the passwords real users actually type. The Prufa check: the forms analyzer observes the validation behavior across multiple attempts. 5-minute manual check: in the signup form, type an 8-character password. The form should either accept it (because your policy is permissive) or show a clear inline error (because your policy isn’t). If it silently submits and 500s, the validation is broken.

  5. OAuth blocked on mobile Safari. “Sign in with Google” opens a popup on desktop, which Safari iOS blocks by default. The user sees a blank popup or nothing. They don’t know to tap “Use email instead.” They abandon. Why vibe coding causes it: the LLM uses the standard Google sign-in library, which assumes a desktop browser context. Mobile Safari’s popup blocker is invisible to the LLM. The Prufa check: the audit walks the flow in a phone-width viewport and watches for OAuth popups; BLOCKED is a state the audit reports honestly (not an error, not a pass). 5-minute manual check: open your site in Safari on an iPhone. Tap “Sign in with Google.” If nothing happens, you have this bug.

The community also names a sixth, more diagnostic, failure mode: the audit itself returns BLOCKED. If your site uses reCAPTCHA or hCaptcha, the LLM-driven flow detection can’t pass it; per the RunStatus enum, BLOCKED is a state, not an error — the report doesn’t render, and you don’t know why. This isn’t a “your signup is broken” failure; it’s a “the tool can’t see your signup” failure. The manual checks above are the workaround.

How Prufa walks a signup flow

The signup flow is the load-bearing example of a pattern Prufa runs everywhere: an LLM does the navigation, plain code does the verification. The LLM looks at the page the way a real user would — reads the visible text, picks the signup button, fills the form, submits. Plain code, against captured browser evidence, verifies that the submission actually worked: the network request returned 200, the auth cookie got set with the Secure flag. The LLM does not grade the result — its blind spots can’t become the verifier’s blind spots because the verifier is plain code and doesn’t share them. For the full walkthrough, see How Prufa verifies a signup flow. For the broader case for why this architecture matters, see Why Prufa exists: QA built for the agentic era.

What the free 60-second audit does for signup flows

The free audit on prufa.dev — run it as the 60-second signup audit — opens your entry URL on a real browser, walks the signup form, submits it, and verifies the success page loaded. The audit also walks one inner page as the authenticated user — which means it can catch the silent failures (success page returns 200 but the auth state never set) that a static checker can’t. No signup, no card.

For the broader pre-launch surface (sitemaps, meta tags, broken links, console errors, the rest of the static- checker list), see Website QA checklist before launch, ordered by what actually breaks. The signup-flow piece is what static checkers don’t cover. If your app also takes money, the same functional-flow gap applies to the highest-stakes flow you have — test your checkout flow before launch, walking it safely up to the payment wall. And if your only conversion path is a contact or lead form, the same gap applies — it can submit cleanly and still never deliver the email. And the flow a locked-out user has no way around — test your password reset flow before launch — is the hardest one of all to verify from the outside. And signup’s twin, the flow every returning user opens, is your login flow — where the failure isn’t a rejected signup but a session that silently won’t stick.

If the team that shipped the change is the marketing team — a landing page update, a banner, a new paid destination — verify your tracking survived the deploy on the marketer version of the same audit. The signup flow matters; the pixels and event payload matter as much. And if you’re a solo founder racing to ship, this is launch QA for indie hackers — the pre-launch flow check before you post the launch tweet.

What the audit doesn’t do (honest limits)

The free audit can’t pass a reCAPTCHA, can’t exercise OAuth without a Google account, and can’t verify that an email actually arrived. Those are the parts the founder has to test themselves; the manual checklist below is the workaround.

What to do before you launch

In order of how often the failure shows up in founder reports:

  1. Test signup with a fresh email address. Read the inbox. Did the verification email arrive in under a minute? Is it in spam? If it’s in spam, fix your SPF/DKIM/DMARC records. If it never arrived, your send code is broken.
  2. Test with a deliberately-too-short password. If your policy is min-length 8, try 6. The form should reject it inline with a clear message. If it silently accepts and the server 500s, validation is broken.
  3. Test from a phone browser, ideally Safari iOS. Tap “Sign in with Google.” If a popup opens, fine. If nothing happens, you have the OAuth/Safari bug.
  4. Watch the network tab during signup. The form should POST to your expected /signup endpoint, get 200 back, and the next page request should carry a Set-Cookie: session=...; Secure; HttpOnly header. If any of those are wrong, you have a flow-graph bug.
  5. Try signup on a slow connection. Throttle your network to 3G. The success page should still load cleanly with the auth state set. If the UI says “Welcome” but the dashboard is blank, you have a race condition between client-side state and server- side state.

FAQ

How do I test a signup flow before launch?

The fastest first step is a free 60-second audit that exercises your entry page, the signup form, and the success page on a real browser. Combine that with five manual checks before launch: test signup with a fresh email, test with a too-short password, test from a phone browser, watch the network tab during signup, and try a slow connection. No single tool catches everything; the combination does.

Why does my signup form not work in production?

The most common reason, by a wide margin in founder reports on Reddit and HN, is email verification that breaks silently — the form submits, the user record is created, the email goes to spam or never arrives, and the user is locked out. The signup looks like it worked; nothing actually works. Other common causes: the success redirect updates UI but the server-side state never updates, the form posts to the wrong endpoint, or the password validator rejects valid passwords.

What is the best way to automate signup flow testing?

A short, deterministic script that walks the entry page, fills the form with a fresh email, submits, and asserts the success page loaded — maintained against captured browser evidence, not screen comparisons. For vibe-coded apps that change every week, deterministic scripts are brittle; the navigator (an LLM) and the verifier (plain code) need to be separate. Continuous monitoring on every PR is the upgrade after launch.

Frequently asked questions

How do I test a signup flow before launch?

The fastest first step is a free 60-second audit that exercises your entry page, the signup form, and the success page on a real browser. Combine that with five manual checks before launch: test signup with a fresh email, test with a too-short password, test from a phone browser, watch the network tab during signup, and try a slow connection. No single tool catches everything; the combination does.

Why does my signup form not work in production?

The most common reason, by a wide margin in founder reports on Reddit and HN, is email verification that breaks silently — the form submits, the user record is created, the email goes to spam or never arrives, and the user is locked out. The signup looks like it worked; nothing actually works. Other common causes: the success redirect updates UI but the server-side state never updates, the form posts to the wrong endpoint, or the password validator rejects valid passwords.

What is the best way to automate signup flow testing?

A short, deterministic script that walks the entry page, fills the form with a fresh email, submits, and asserts the success page loaded — maintained against captured browser evidence, not screen comparisons. For vibe-coded apps that change every week, deterministic scripts are brittle; the navigator (an LLM) and the verifier (plain code) need to be separate. Continuous monitoring on every PR is the upgrade after launch.