Build a settings page with four sections: Profile (CircleImage avatar with camera overlay, name edit), Preferences (dark mode Switch bound to App State, language DropDown), Account (change password link, delete account with confirmation dialog), and About (app version via package_info, Terms/Privacy links, Rate Us link). Delete account deletes the user's Firestore document and subcollections first, then deletes the Firebase Auth account.
Building a Complete App Settings Page in FlutterFlow
Every app needs a settings page. This tutorial builds a production-ready settings screen with profile management, appearance preferences, account actions, and app information — organized into clear sections using the ListTile row pattern.
Prerequisites
- A FlutterFlow project with Firestore and Firebase Authentication configured
- A users collection with documents storing displayName, photoUrl, and preferences
- Terms of Service and Privacy Policy pages already created
Step-by-step guide
Build the Profile section with CircleImage avatar and name edit Row
Build the Profile section with CircleImage avatar and name edit Row
At the top of the SettingsPage Column, add a Container (padding: 24, center alignment). Inside, add a Stack: CircleImage (radius: 50, bound to currentUser.photoUrl, default placeholder avatar) with a Positioned bottom-right Container (circle, primary color, size: 30) containing an Icon (camera_alt, white, size: 16). On the camera overlay tap, trigger Upload Media → Upload to Firebase Storage at path users/{uid}/avatar.png → Update user document photoUrl field. Below the avatar, add a Row: Text (currentUser.displayName, titleLarge) and an IconButton (edit, On Tap → Show Dialog with TextField for new name → Update Document displayName).
Expected result: The profile section shows the user's avatar with a camera change button and their display name with an edit button.
Add a Preferences section with dark mode Switch and language DropDown
Add a Preferences section with dark mode Switch and language DropDown
Add a Text section header 'Preferences' (titleMedium, bold, padding top 24). Add a ListTile Row: Icon (dark_mode), Column ('Dark Mode' title, 'Switch between light and dark themes' subtitle), trailing Switch. Create an App State variable isDarkMode (Boolean, persisted, default false). Bind the Switch value to isDarkMode. On Switch toggle, update isDarkMode and call Set Dark Mode Custom Action that sets FlutterFlow's ThemeMode. Below, add another ListTile Row: Icon (language), Column ('Language'), trailing DropDown with options (English, Spanish, French, German). Bind to App State selectedLanguage (String, persisted).
Expected result: Toggling the dark mode Switch immediately changes the app theme. The language DropDown persists the selected language.
Add an Account section with change password link and delete account with confirmation
Add an Account section with change password link and delete account with confirmation
Add a Text section header 'Account'. Add a ListTile Row: Icon (lock_outline), Text 'Change Password', trailing Icon (chevron_right). On Tap → trigger Firebase Auth Send Password Reset Email to currentUser.email → show SnackBar 'Password reset email sent'. Add another ListTile Row: Icon (delete_forever, red), Text 'Delete Account' (red), trailing Icon (chevron_right, red). On Tap → Show Dialog with a confirmation Component: 'Are you sure? This cannot be undone.' with Cancel and Delete buttons. On Delete confirm → Custom Action that: (1) deletes user subcollections (orders, notifications), (2) deletes the user document, (3) calls FirebaseAuth.instance.currentUser!.delete(), (4) navigates to the login page with Replace Route.
Expected result: Change password sends a reset email. Delete account shows a confirmation dialog and, on confirm, removes all user data and the auth account.
Add an About section with app version, legal links, and Rate Us
Add an About section with app version, legal links, and Rate Us
Add a Text section header 'About'. Add a ListTile Row: Icon (info_outline), Text 'Version', trailing Text bound to Page State appVersion. On Page Load, run a Custom Action using package_info_plus to get the version string. Add ListTile Rows for: 'Terms of Service' (On Tap → Navigate to TOS page), 'Privacy Policy' (On Tap → Navigate to Privacy page), 'Rate This App' (On Tap → Launch URL to App Store / Play Store listing). Add a Logout Button at the very bottom: full-width, outlined style, red text. On Tap → Firebase Auth Sign Out → Navigate to login with Replace Route.
Expected result: The About section shows the live app version, links to legal pages, a rate-us link, and a logout button.
Add Dividers between sections and wrap everything in SingleChildScrollView
Add Dividers between sections and wrap everything in SingleChildScrollView
Wrap the entire Column in a SingleChildScrollView so the settings page scrolls on smaller screens. Add Divider widgets between each section (Profile, Preferences, Account, About) with indent: 16 for visual separation. Apply consistent padding (horizontal: 16) to all ListTile Rows. Ensure all trailing widgets (Switch, DropDown, chevron icons) align vertically by setting a fixed trailing width or using Expanded + Align.
Expected result: The settings page scrolls smoothly with clear visual separation between sections and consistent alignment across all rows.
Complete working example
1PAGE: SettingsPage2 Page State: appVersion (String)3 App State: isDarkMode (Boolean, persisted), selectedLanguage (String, persisted)45WIDGET TREE:6 Scaffold7 AppBar (title: "Settings")8 SingleChildScrollView9 Column (crossAxisAlignment: stretch)10 ├── PROFILE SECTION11 │ Container (padding: 24, center)12 │ Column (center)13 │ ├── Stack14 │ │ ├── CircleImage (radius: 50, photoUrl)15 │ │ └── Positioned (bottom: 0, right: 0)16 │ │ Container (circle, primary, size: 30)17 │ │ Icon (camera_alt, white, 16)18 │ │ On Tap → Upload Media → Update photoUrl19 │ ├── SizedBox (8)20 │ └── Row (center)21 │ ├── Text (displayName, titleLarge)22 │ └── IconButton (edit)23 │ On Tap → Show Dialog → TextField → Update displayName24 ├── Divider (indent: 16)25 ├── PREFERENCES SECTION26 │ Text "Preferences" (titleMedium, bold, padding: 24 16 8 16)27 │ Row (padding: 12 16) — Dark Mode28 │ ├── Icon (dark_mode)29 │ ├── SizedBox (12)30 │ ├── Expanded Column31 │ │ ├── Text "Dark Mode" (bodyLarge)32 │ │ └── Text "Switch between light and dark" (bodySmall, grey)33 │ └── Switch (isDarkMode)34 │ On Changed → Update App State → Set Theme Mode35 │ Row (padding: 12 16) — Language36 │ ├── Icon (language)37 │ ├── SizedBox (12)38 │ ├── Expanded Text "Language" (bodyLarge)39 │ └── DropDown (English, Spanish, French, German)40 │ Bound to selectedLanguage41 ├── Divider (indent: 16)42 ├── ACCOUNT SECTION43 │ Text "Account" (titleMedium, bold, padding: 24 16 8 16)44 │ Row (padding: 12 16) — Change Password45 │ ├── Icon (lock_outline)46 │ ├── SizedBox (12)47 │ ├── Expanded Text "Change Password" (bodyLarge)48 │ └── Icon (chevron_right, grey)49 │ On Tap → Send Password Reset Email → SnackBar50 │ Row (padding: 12 16) — Delete Account51 │ ├── Icon (delete_forever, red)52 │ ├── SizedBox (12)53 │ ├── Expanded Text "Delete Account" (bodyLarge, red)54 │ └── Icon (chevron_right, red)55 │ On Tap → Show Confirmation Dialog56 │ On Confirm → Delete subcollections → Delete user doc → Delete Auth → Navigate login57 ├── Divider (indent: 16)58 ├── ABOUT SECTION59 │ Text "About" (titleMedium, bold, padding: 24 16 8 16)60 │ Row — Version: trailing Text (appVersion)61 │ Row — Terms of Service: On Tap → Navigate TOS62 │ Row — Privacy Policy: On Tap → Navigate Privacy63 │ Row — Rate This App: On Tap → Launch URL store listing64 ├── SizedBox (24)65 └── Button "Log Out" (outlined, red, full width, margin: 16)66 On Tap → Sign Out → Navigate login (Replace Route)6768ON PAGE LOAD:69 1. Custom Action getAppVersion → set appVersion7071DELETE ACCOUNT CUSTOM ACTION:72 1. Delete user subcollections (orders, notifications)73 2. Delete users/{uid} document74 3. FirebaseAuth.instance.currentUser!.delete()75 4. Navigate to LoginPage with Replace RouteCommon mistakes when creating a Custom Settings Screen for Your FlutterFlow App
Why it's a problem: Only deleting the Firebase Auth account without deleting the Firestore user document and subcollections
How to avoid: Delete all Firestore documents and subcollections for the user first, then delete the Auth account as the final step.
Why it's a problem: Storing dark mode preference in Page State instead of persisted App State
How to avoid: Use an App State boolean with Persisted enabled. The dark mode preference survives page navigation and app restarts.
Why it's a problem: Not wrapping the settings Column in SingleChildScrollView
How to avoid: Wrap the entire Column in a SingleChildScrollView so all settings sections are accessible via scrolling.
Best practices
- Organize settings into clear sections (Profile, Preferences, Account, About) with Dividers between them
- Use the ListTile Row pattern (Icon + Title/Subtitle + trailing widget) for consistent visual alignment
- Persist all preference values (dark mode, language) in App State with Persisted enabled
- Require a confirmation dialog before destructive actions like delete account
- Delete Firestore data before deleting the Auth account — once Auth is deleted, you lose the UID reference
- Display the live app version using package_info_plus so users always know which version they are running
- Use Replace Route for logout and delete account navigation so users cannot press Back to return
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a complete settings page in FlutterFlow with sections for profile editing (avatar + name), preferences (dark mode toggle + language dropdown), account management (change password + delete account), and about (version + legal links + logout). Show me the widget tree, App State setup, and the delete account flow.
Create a settings page with a profile avatar at the top, toggle switches for dark mode and notifications, a language dropdown, change password and delete account rows, and links to terms, privacy, and rate us at the bottom.
Frequently asked questions
How do I make the dark mode toggle take effect immediately across all pages?
Update the persisted App State isDarkMode variable and call a Custom Action that sets FlutterFlow's ThemeMode to ThemeMode.dark or ThemeMode.light. Since ThemeMode is applied at the MaterialApp level, all pages update instantly.
What happens if the user deletes their account while offline?
Firestore deletes are queued locally and execute when connectivity returns. However, the Auth delete call will fail offline. Add error handling to show a message asking the user to reconnect before deleting.
Can I add a profile photo crop before uploading?
Yes. After the Upload Media picker returns an image, pass it to an image cropper Custom Widget or use the image_cropper package in a Custom Action before uploading to Firebase Storage.
How do I handle the language selector changing the app language?
Store the selected locale in App State. Use FlutterFlow's built-in Internationalization feature (Settings → General → Languages) to define translated strings. Set the app locale based on the App State value on app startup.
Should I use Firebase Auth reauthentication before account deletion?
Yes. Firebase requires recent authentication for sensitive operations. Before calling delete(), prompt the user for their password and call reauthenticateWithCredential(). This prevents the requires-recent-login error.
Can RapidDev help build a complete user management system?
Yes. RapidDev can implement profile management, account settings, role-based permissions, subscription billing integration, and admin user management dashboards.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation