A real-time messaging application built with Flutter and Firebase, enabling users to sign up, log in, and chat with other users seamlessly.
- User authentication (Sign up and Log in) with state management
- Real-time chat messaging
- User discovery and listing
- User profile management
- Persistent authentication state
- Offline support with cached data
- Clean and intuitive UI
- Form validation with reactive state management
- Authentication state management using Riverpod
The app implements comprehensive form validation using Riverpod for reactive state management:
- Email validation with regex pattern matching
- Password strength validation
- Confirm password matching
- Real-time validation feedback
- Disabled submit button until all fields are valid
- Error message display on form fields
- Form state reset after successful submission
The app uses Riverpod for efficient authentication state management:
- Authentication status tracking (authenticated, unauthenticated, loading)
- User session persistence
- Automatic token refresh
- Logout functionality with state cleanup
- Deep linking based on authentication state
Riverpod manages all chat-related states:
- Active chat selection
- Message list streaming
- Real-time message updates
- Message sending status
- Unread message count
- Chat list management
User data and profile state management:
- User list caching
- User profile updates
- User search functionality
- Profile image upload status
Before getting started, ensure you have the following installed:
- Flutter SDK (version 3.0 or higher)
- Dart SDK
- Firebase CLI
- Android Studio or Xcode (for iOS development)
- A Firebase project
git clone <repository-url>
cd flutter-firebase-chat-appflutter pub get- Download
google-services.jsonfrom your Firebase console - Place it in
android/app/directory
- Download
GoogleService-Info.plistfrom your Firebase console - Add it to the Xcode project (Runner > Add files)
flutter runlib/
├── main.dart
├── models/
│ ├── user_model.dart
│ └── message_model.dart
├── screens/
│ ├── auth/
│ │ ├── login_screen.dart
│ │ ├── signup_screen.dart
│ │ └── auth_wrapper.dart
│ ├── home/
│ │ ├── home_screen.dart
│ │ ├── users_list_screen.dart
│ │ └── user_profile_screen.dart
│ └── chat/
│ └── chat_screen.dart
├── providers/
│ ├── auth_provider.dart
│ ├── auth_notifier.dart
│ ├── form_provider.dart
│ ├── user_provider.dart
│ ├── chat_provider.dart
│ └── message_provider.dart
├── services/
│ ├── firebase_auth_service.dart
│ ├── firestore_service.dart
│ └── storage_service.dart
├── widgets/
│ ├── chat_bubble.dart
│ ├── message_input.dart
│ ├── user_card.dart
│ └── form_fields.dart
└── utils/
├── validators.dart
└── constants.dart
- Launch the app
- Tap "Sign Up"
- Enter email (real-time validation)
- Enter password (minimum 6 characters)
- Confirm password (must match)
- Complete your profile information
- Submit button enables only when all fields are valid
- Tap "Create Account"
- Enter your registered email
- Enter your password
- Form validates inputs in real-time
- Tap "Log In"
- Authentication state updates automatically
- Go to "Users" tab to see all available users
- Tap on a user to open chat
- Type your message and send
- Messages appear in real-time for both users
- Tap "Profile" tab
- View your profile information
- Edit your details if needed
- Profile updates are reflected in real-time across the app
- Flutter - Cross-platform mobile framework
- Firebase Authentication - User authentication with state persistence
- Firestore - Real-time database with stream providers
- Firebase Cloud Storage - Profile image storage
- Riverpod - State management with providers, notifiers, and families
- Dart - Programming language
users - User account information
chats - Chat conversations
messages - Individual messages
1. StreamProviders - Real-time data streams
- Authentication state stream
- Messages stream
- Users list updates
2. FutureProviders - Async data fetching
- Fetch user profile
- Load users list
- Get chat history
3. StateProviders - Simple state containers
- Selected chat ID
- Current form values
- UI state (loading, error)
4. StateNotifierProviders - Complex state logic
- Authentication notifier (signup, login, logout)
- Form validation notifier
- Message sending notifier
- Profile update notifier
- User launches app
- Riverpod checks
authStateProviderfor existing session - If authenticated, navigate to home screen
- If unauthenticated, navigate to login/signup
- User form inputs trigger validation providers
- On submit, authentication notifier processes signup/login
- Firebase updates authentication state
- Stream providers automatically update UI with new state
- User data syncs across all relevant providers
- Form validation errors shown on individual fields
- Network errors displayed with retry options
- Authentication failures with user-friendly messages
- Firestore permission errors with guidance
- Sign Up - Creates new user account with validation
- Log In - Authenticates user with credentials
- Log Out - Ends user session and clears state
- Send Message - Creates new message in Firestore
- Fetch Messages - Retrieves chat history via stream
- Mark as Read - Updates message read status
- Get User List - Retrieves all users with caching
- Get User Profile - Fetches user details
- Update Profile - Modifies user information with notifier
- Verify Firebase credentials are correctly configured
- Check internet connection
- Ensure Firebase project is active
- Verify email format is correct
- Ensure password meets Firebase requirements (minimum 6 characters)
- Check that user account exists for login
- Confirm Firestore rules allow read/write permissions
- Check user permissions in Firestore
- Verify chat participants are correctly stored
- Clear app cache and rebuild
- Ensure validators are called on every field change
- Check form state provider is properly initialized
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/YourFeature) - Commit your changes (
git commit -m 'Add YourFeature') - Push to the branch (
git push origin feature/YourFeature) - Open a Pull Request