Build a registration page with name, email, password (with a real-time strength meter using LinearPercentIndicator), confirm password, and a TOS agreement checkbox. The sign-up action flow creates the Firebase Auth account first, then writes a user document to Firestore with displayName, email, and createdAt. A Custom Function calculates password strength by checking length, uppercase, number, and special character — returning a 0.0 to 1.0 score that colors the progress bar red, orange, or green. After sign-up, send a verification email.
Building a Registration Page with Password Strength Meter and Email Verification in FlutterFlow
A good sign-up screen balances security with usability. This tutorial builds a registration form with real-time password strength feedback, terms agreement enforcement, and a two-step creation flow (Auth account first, then Firestore user document) to prevent orphaned data.
Prerequisites
- A FlutterFlow project with Firebase Authentication and Firestore configured
- Email/Password sign-in method enabled in Firebase console
- A users collection in Firestore for storing user profile data
- A Terms of Service page already created for linking
Step-by-step guide
Build the registration form with name, email, password, and confirm password TextFields
Build the registration form with name, email, password, and confirm password TextFields
Create a SignUpPage with a SingleChildScrollView containing a Column (padding: 24). Add: Text 'Create Account' (headlineMedium, bold), SizedBox(24), TextField 'Full Name' (prefixIcon: person, textCapitalization: words), SizedBox(16), TextField 'Email' (prefixIcon: email, keyboardType: emailAddress), SizedBox(16), TextField 'Password' (prefixIcon: lock, obscureText with visibility toggle suffix, hintText: 'At least 8 characters'), SizedBox(8) — the strength meter goes here (next step), SizedBox(16), TextField 'Confirm Password' (prefixIcon: lock_outline, obscureText). Create Page State variables for all four field values plus isPasswordVisible (Boolean).
Expected result: The sign-up form shows four labeled TextFields with proper keyboard types and a password visibility toggle.
Create a passwordStrength Custom Function and bind it to a LinearPercentIndicator
Create a passwordStrength Custom Function and bind it to a LinearPercentIndicator
Create a Custom Function passwordStrength(String password) that returns a double from 0.0 to 1.0. Logic: start with score 0.0. Add 0.25 if password.length >= 8. Add 0.25 if password contains an uppercase letter (RegExp r'[A-Z]'). Add 0.25 if password contains a digit (RegExp r'[0-9]'). Add 0.25 if password contains a special character (RegExp r'[!@#$%^&*]'). Return the score. Below the password TextField, add a LinearPercentIndicator (lineHeight: 6, percent: bound to passwordStrength(passwordValue), backgroundColor: grey200). Set progressColor conditionally: red if score < 0.5, orange if < 0.75, green if >= 0.75. Below the bar, add a Text showing 'Weak', 'Medium', or 'Strong' with matching color.
Expected result: As the user types their password, the strength bar fills and changes color from red to orange to green in real time.
Add the TOS checkbox with tappable Terms and Privacy links
Add the TOS checkbox with tappable Terms and Privacy links
Below the confirm password field, add a Row: Checkbox bound to Page State tosAccepted (Boolean) + RichText with plain text 'I agree to the ' + tappable TextSpan 'Terms of Service' (underline, primary color, On Tap → Navigate to TOS page) + plain text ' and ' + tappable TextSpan 'Privacy Policy' (underline, primary color, On Tap → Navigate to Privacy page). The Create Account Button below should be disabled (Conditional property: enabled = tosAccepted && all fields non-empty && password == confirmPassword).
Expected result: The checkbox must be checked and all fields valid before the Create Account button becomes active. Terms and Privacy links navigate to their respective pages.
Implement the sign-up action: create Auth account first, then Firestore user document
Implement the sign-up action: create Auth account first, then Firestore user document
On the Create Account Button tap: (1) Validate — email format, password length >= 8, password == confirmPassword, tosAccepted is true. Show SnackBar for any failure. (2) Call Firebase Auth Create Account (email, password). (3) On Auth success, immediately Create Document in users collection: uid (currentUser.uid), displayName (nameValue), email (emailValue), photoUrl (''), createdAt (Timestamp.now()), tosAccepted (true), tosAcceptedAt (Timestamp.now()). (4) On Firestore success → Send Email Verification (Firebase Auth action). (5) Navigate to HomePage with Replace Route. Creating Auth first prevents orphaned Firestore documents if the email is already taken.
Expected result: Sign-up creates the Auth account, writes the user profile to Firestore, sends a verification email, and navigates to home.
Handle Firebase Auth errors for duplicate email, weak password, and invalid email
Handle Firebase Auth errors for duplicate email, weak password, and invalid email
On the Auth Create Account failure branch, add Conditional Actions: if error code contains 'email-already-in-use' → Show SnackBar 'An account with this email already exists. Try logging in.' If 'weak-password' → Show SnackBar 'Password is too weak. Use at least 8 characters with uppercase, numbers, and special characters.' If 'invalid-email' → Show SnackBar 'Please enter a valid email address.' Default → Show SnackBar 'Sign-up failed. Please try again.' All error SnackBars use red background. Also add a try-catch around the Firestore Create Document — if it fails, delete the Auth account to avoid an auth-only orphan.
Expected result: Each sign-up error shows a specific, helpful message. If Firestore write fails after Auth creation, the Auth account is cleaned up.
Complete working example
1PAGE: SignUpPage2 Page State: nameValue, emailValue, passwordValue, confirmPasswordValue (String)3 isPasswordVisible (Boolean), tosAccepted (Boolean)45WIDGET TREE:6 Scaffold7 SingleChildScrollView8 Column (padding: 24, crossAxisAlignment: stretch)9 ├── Text "Create Account" (headlineMedium, bold)10 ├── Text "Sign up to get started" (bodyMedium, grey)11 ├── SizedBox (24)12 ├── TextField "Full Name"13 │ prefixIcon: person, textCapitalization: words14 │ On Changed → set nameValue15 ├── SizedBox (16)16 ├── TextField "Email"17 │ prefixIcon: email, keyboardType: emailAddress18 │ On Changed → set emailValue19 ├── SizedBox (16)20 ├── TextField "Password"21 │ prefixIcon: lock22 │ obscureText: !isPasswordVisible23 │ suffixIcon: visibility toggle24 │ hintText: "At least 8 characters"25 │ On Changed → set passwordValue26 ├── SizedBox (8)27 ├── LinearPercentIndicator28 │ lineHeight: 6, borderRadius: 329 │ percent: passwordStrength(passwordValue)30 │ progressColor: red (<0.5) | orange (<0.75) | green (>=0.75)31 │ backgroundColor: grey20032 ├── Text ("Weak" | "Medium" | "Strong", bodySmall, matching color)33 ├── SizedBox (16)34 ├── TextField "Confirm Password"35 │ prefixIcon: lock_outline, obscureText: true36 │ On Changed → set confirmPasswordValue37 ├── SizedBox (16)38 ├── Row39 │ ├── Checkbox (tosAccepted)40 │ └── RichText41 │ "I agree to the "42 │ [Terms of Service] (tappable, underline, primary)43 │ " and "44 │ [Privacy Policy] (tappable, underline, primary)45 ├── SizedBox (24)46 ├── Button "Create Account" (full width, primary)47 │ Enabled: tosAccepted && all fields valid && password == confirmPassword48 │ On Tap:49 │ 1. Validate fields50 │ 2. Auth Create Account (email, password)51 │ 3. Create Document users/{uid} (displayName, email, createdAt, tosAccepted)52 │ 4. Send Email Verification53 │ 5. Navigate HomePage (Replace Route)54 │ On Failure → error-specific SnackBar55 ├── SizedBox (16)56 └── Row (center)57 ├── Text "Already have an account?"58 └── TextButton "Log In" → Navigate LoginPage5960CUSTOM FUNCTION passwordStrength(String password) → double:61 score = 0.062 if (password.length >= 8) score += 0.2563 if (RegExp(r'[A-Z]').hasMatch(password)) score += 0.2564 if (RegExp(r'[0-9]').hasMatch(password)) score += 0.2565 if (RegExp(r'[!@#$%^&*]').hasMatch(password)) score += 0.2566 return scoreCommon mistakes when creating a Custom Sign-Up Screen for Your FlutterFlow App
Why it's a problem: Creating the Firestore user document before creating the Firebase Auth account
How to avoid: Always create the Auth account first. Only write the Firestore user document after Auth succeeds. If the Firestore write fails, delete the Auth account to clean up.
Why it's a problem: Not disabling the Create Account button until the TOS checkbox is checked
How to avoid: Use a Conditional property on the Button: enabled = tosAccepted && passwordValue == confirmPasswordValue && all fields non-empty.
Why it's a problem: Checking password strength only on submit instead of in real time
How to avoid: Bind the LinearPercentIndicator to passwordStrength(passwordValue) which recalculates on every keystroke via On Changed, giving instant visual feedback.
Best practices
- Create the Auth account before the Firestore document to prevent orphaned data on failure
- Show password strength in real time with a color-coded progress bar so users fix issues as they type
- Require the TOS checkbox and disable the submit button until all validations pass
- Send email verification immediately after account creation to confirm the email address
- Use SingleChildScrollView on the form page to handle keyboard overflow on small screens
- Pre-validate confirm password match before submitting to avoid unnecessary Auth API calls
- Link Terms and Privacy as tappable RichText spans so users can read them before agreeing
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a sign-up screen in FlutterFlow with name, email, password with strength meter, confirm password, and a TOS checkbox. Show me the password strength Custom Function, the LinearPercentIndicator binding, the Auth + Firestore creation order, and error handling for duplicate email.
Create a registration page with full name, email, password, confirm password fields. Add a colored progress bar below the password that shows strength. Include a terms checkbox and a create account button at the bottom.
Frequently asked questions
How does the password strength meter calculate the score?
The Custom Function checks four criteria: length >= 8 characters, contains uppercase letter, contains digit, and contains special character. Each adds 0.25 to the score, giving a range of 0.0 (none met) to 1.0 (all met).
What happens if the Firestore document creation fails after Auth account creation?
You should catch the Firestore error and delete the just-created Auth account with currentUser.delete() to avoid an auth-only orphan. Then show an error SnackBar asking the user to try again.
Can I add a profile photo upload during registration?
Yes. Add an optional step after the main form: show a CircleImage placeholder with a camera IconButton overlay. On tap, use Upload Media → Firebase Storage → save the URL in the user document's photoUrl field.
How do I enforce email verification before allowing app access?
After login, check currentUser.emailVerified. If false, navigate to an EmailVerificationPage that displays a message and a Resend button. Block access to the main app until verified.
Can I add multi-step registration with a progress indicator?
Yes. Use a PageView with Step 1 (credentials) and Step 2 (profile info like avatar and bio). Add a LinearPercentIndicator at the top showing step 1 of 2 / step 2 of 2.
Can RapidDev help build an advanced onboarding and auth system?
Yes. RapidDev can implement multi-step registration, social auth, phone verification, role-based access, invite-only signups, and KYC identity verification workflows.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation