brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
signup-flow-croAudits and improves an account-creation flow so that more of the people who start signing up finish: the form fields, markup, sign-in methods, password rules, email verification, error handling, and the measurement that proves a change worked. Use when a user asks to "improve signup conversion", "reduce registration drop-off", "review our sign-up form", "to…
Independent GitHub snapshot · Automated classification · Original documentation governs
A signup flow is everything between the click on "Sign up" and the first screen of the product: the form, the choice of sign-in method, verification, and any questions asked on the way. People leave it for a small number of reasons: it asks for more than they are ready to give, the form fights their browser or password manager, an error wipes their input or does not say what to fix, or a verification step sends them away and they never return.
This skill works from evidence. It maps the flow from the code, measures each step, removes or postpones what is not needed, corrects the markup so autofill and assistive technology work, and specifies how the change will be judged. It ends at the first product screen; activation after that is a different job.
Locate and read: the signup route and form component, the client and server validation rules, the auth provider or library configuration, the email or SMS verification handler, and the redirect after success. Write the flow as numbered steps with, for each step, the fields, which are required, and what a user must do outside the page (open an email, switch app).
Ask the user for what the code cannot show: step-by-step numbers from analytics, the device split, which collected fields are used in the first week and by whom, and any legal or security constraint (age checks, business customers only, mandatory second factor).
If step-level numbers do not exist, add events first and collect a baseline. A minimal set:
| Event | When | Parameters |
|---|---|---|
signup_view | The form is rendered | variant |
signup_start | First interaction with any field or sign-in button | method |
signup_error | A validation or server error is shown | field, reason, method |
sign_up | The account exists (GA4's recommended event name) | method |
signup_verified | Email or phone confirmed | method, minutes_to_verify |
// fire once, on the user's first focus or click inside the form
gtag("event", "signup_start", { method: "email" });
// fire from the success handler, never on button click
gtag("event", "sign_up", { method: "google" });
Report three rates, split by device and by method: start rate (signup_start / signup_view), completion rate (sign_up / signup_start), verified rate (signup_verified / sign_up). Never put an email address or other personal data in an event parameter.
Go through the fields one by one and assign exactly one outcome:
| Outcome | Test | Typical cases |
|---|---|---|
| Keep | The account cannot be created or used without it | Email or phone, a credential, legally required consent |
| Infer | It can be derived without asking | Country from locale, company from email domain, name from the identity provider |
| Postpone | It is useful, but only after the user has seen the product | Role, team size, use case, phone number, avatar |
| Drop | Nobody can name the report or feature that uses it | Second address line, "how did you hear about us" when attribution already exists |
Postponed questions move to the first product screens, where they can be skipped. If sales insists on a qualifying field, keep one, make it a choice rather than free text, and put it after the credential fields.
The reference below is the target shape for an email-and-password form. Adapt names to the project's components but keep the attributes.
<form id="signup" method="post" action="/signup" novalidate>
<label for="email">Work email</label>
<input id="email" name="email" type="email" autocomplete="email"
spellcheck="false" required aria-describedby="email-error">
<p id="email-error" role="alert" hidden></p>
<label for="password">Password</label>
<input id="password" name="password" type="password" autocomplete="new-password"
minlength="15" maxlength="128" required aria-describedby="password-hint password-error">
<button type="button" id="toggle-password" aria-controls="password" aria-pressed="false">Show password</button>
<p id="password-hint">At least 15 characters. A phrase of several words works well.</p>
<p id="password-error" role="alert" hidden></p>
<button type="submit">Create account</button>
<p>By creating an account you agree to the <a href="/terms">Terms</a> and <a href="/privacy">Privacy Policy</a>.</p>
</form>
Checks that apply to any stack:
label; placeholder text is not a label and disappears on typing.autocomplete tokens are exact: email, username, new-password on signup (current-password only on sign-in), name or given-name and family-name, organization, tel, one-time-code for emailed or texted codes.type="email" and type="tel" bring up the right mobile keyboard; a numeric code field uses type="text" with inputmode="numeric", not type="number".method value so its completion rate is visible.aria-describedby, and sets aria-invalid="true".Ship plain defect fixes (broken autofill, lost input, missing labels) without an experiment and compare the three rates before and after. Run an A/B test for changes with a real trade-off: removing a qualifying field, changing the method on offer, moving verification.
from statistics import NormalDist
def sample_size_per_variant(baseline, relative_lift, alpha=0.05, power=0.8):
"""Visitors who start the form, per variant, for a two-sided test of two proportions."""
p1, p2 = baseline, baseline * (1 + relative_lift)
z = NormalDist().inv_cdf(1 - alpha / 2) + NormalDist().inv_cdf(power)
return round(z ** 2 * (p1 * (1 - p1) + p2 * (1 - p2)) / (p2 - p1) ** 2)
Divide the result by weekly form starts per variant to get the duration; if that exceeds about six weeks, test a bolder change or accept a before-and-after comparison. Judge on completion and on a downstream measure (verified accounts, accounts active after seven days, qualified leads), because a shorter form can raise sign-ups and lower their quality.
step | observation | evidence (code location or metric) | change | metric it should move | effort.Request: "Nimble Trellis is a project planning tool. Our signup at app/signup/page.tsx has seven fields and 31% of people who start it finish; on phones it is 19%. About 2,400 people start it each week. Improve it."
Flow map: one step, seven required fields (first name, last name, work email, password, confirm password, company, team size), then an email link that must be clicked before the first sign-in.
| Step | Observation | Evidence | Change | Metric | Effort |
|---|---|---|---|---|---|
| Form | Password rule demands upper case, digit and symbol and is shown only after submit; 22% of submits fail on it | lib/validation.ts regex; signup_error by field | One rule (15+ characters) shown under the field, breached-password check on the server | Completion | S |
| Form | Password input uses autocomplete="off"; generated passwords are rejected | SignupForm.tsx line 48 | autocomplete="new-password", remove the confirm field, add a show toggle | Completion, mobile | S |
| Form | Company and team size are asked before the account exists | Used only by the sales dashboard | Company inferred from the email domain; team size moved to the first project screen, skippable | Completion | M |
| Form | No identity-provider option although 64% of addresses are Google Workspace | Email domain MX sample | Add Google and Microsoft buttons above the form | Start and completion | M |
| After submit | Product is locked until the email link is clicked | middleware.ts redirect | Let users in; require confirmation before inviting teammates | Verified rate, 7-day active | M |
The first two rows are defects and ship immediately. The field removal and the verification change are tested together against the corrected form:
>>> sample_size_per_variant(0.31, 0.15)
1609
With 1,200 starts per variant per week the test needs about ten days; it runs two full weeks to cover weekday patterns. Primary metric: completion rate. Guardrail: share of new accounts that create a project within seven days must not fall.
Request: "Shiftloom is a rota app for cafés; almost all signups are on phones. 1,000 people a week enter their email, but only 540 ever confirm it and get in. What should we change?"
Flow map: (1) email only, (2) "check your inbox" page, (3) link opens the default browser, (4) set password, (5) business name and number of staff.
Findings: the loss sits between steps 2 and 3, a verified rate of 54%. The address field has type="text", so phones show a letter keyboard without "@" and offer no autofill, and mistyped addresses never receive the message. The link opens outside the in-app browser many visitors arrive in from social apps, which starts a new session with no record of the signup. There is no resend or change-address control.
Changes, in order:
type="email" with autocomplete="email"; the server rejects domains without a mail server and the page suggests a correction for common misspellings.type="text", inputmode="numeric", autocomplete="one-time-code", with "Resend code" after 30 seconds and "Use a different email".signup_error with reason values code_wrong, code_expired, email_bounced; signup_verified with minutes_to_verify.The verification change alters behaviour enough to judge without a split test at this volume: compare verified rate for two weeks before and after, with the target set at 75%, and watch seven-day retention as the guardrail.