A professional Flutter application demonstrating best practices in mobile development with Clean Architecture, BLoC state management, and multi-environment support.
ConnectX is a user management application that fetches and displays user information from the ReqRes API. Built with scalability and maintainability in mind, it showcases modern Flutter development practices including Clean Architecture, comprehensive error handling, offline caching, and responsive UI design.
- User List Display - Paginated list with infinite scrolling
- User Search - Real-time search with debouncing (500ms)
- User Details - Comprehensive user profile with smooth animations
- Pull-to-Refresh - Swipe to refresh user data
- Offline Support - Local data persistence using SharedPreferences
- Image Caching - Optimized avatar loading with cached_network_image
- Multi-Environment - Development, Staging, and Production flavors
- Error Handling - Comprehensive error states with retry functionality
- Network Monitoring - Connectivity detection
- Custom Splash Screen - Branded app launch experience
This project implements Clean Architecture with three distinct layers:
┌─────────────────────────────────────────────────┐
│ Presentation Layer │
│ (Pages, Widgets, BLoC State Management) │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Domain Layer │
│ (Entities, Use Cases, Repositories) │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ Data Layer │
│ (Models, Data Sources, Repository Impl) │
└─────────────────────────────────────────────────┘
- Clean Architecture - Separation of concerns across layers
- BLoC Pattern - Business Logic Component for state management
- Repository Pattern - Abstract data sources behind interfaces
- Dependency Injection - GetIt service locator
- Either/Result Pattern - Functional error handling with dartz
- Factory Pattern - Model creation and entity conversion
lib/
├── app/ # Application layer
│ ├── app.dart # Main app widget
│ ├── router/ # Navigation routing (GoRouter)
│ └── theme/ # Material theme configuration
│
├── core/ # Shared utilities & infrastructure
│ ├── config/ # App flavor configuration
│ ├── constants/ # Global constants
│ ├── di/ # Dependency injection setup
│ ├── errors/ # Exception and failure types
│ ├── network/ # HTTP client & network utilities
│ ├── usecases/ # Base use case abstraction
│ └── utils/ # Extensions, validators, logger
│
├── features/ # Feature modules
│ └── user/ # User feature
│ ├── data/ # Data layer
│ │ ├── datasources/ # Remote & Local data sources
│ │ ├── models/ # JSON serializable models
│ │ └── repositories/ # Repository implementations
│ │
│ ├── domain/ # Domain layer
│ │ ├── entities/ # Business entities
│ │ ├── repository/ # Repository interfaces
│ │ └── usecases/ # Business use cases
│ │
│ └── presentation/ # Presentation layer
│ ├── bloc/ # BLoC state management
│ ├── pages/ # Full screen pages
│ └── widgets/ # Reusable UI components
│
├── main_development.dart # Development entry point
├── main_staging.dart # Staging entry point
├── main_production.dart # Production entry point
└── environment_config.dart # Environment variables loader
- Flutter SDK
^3.5.3 - Dart SDK
^3.5.3
- flutter_bloc
^9.1.1- BLoC pattern implementation - equatable
^2.0.7- Value equality - dartz
^0.10.1- Functional programming (Either) - get_it
^8.2.0- Dependency injection
- dio
^5.9.0- HTTP client - connectivity_plus
^7.0.0- Network status monitoring - shared_preferences
^2.5.3- Local storage - cached_network_image
^3.4.1- Image caching
- go_router
^15.1.2- Declarative routing
- flutter_dotenv
^6.0.0- Environment variables - flutter_flavor
^3.1.3- Multi-flavor support
- json_annotation
^4.9.0- JSON annotations - json_serializable
^6.9.0- Code generation - build_runner
^2.4.13- Build system
- pull_to_refresh
^2.0.0- Pull-to-refresh functionality - cupertino_icons
^1.0.8- iOS-style icons
- Flutter SDK (≥3.5.3)
- Dart SDK (≥3.5.3)
- Android Studio / VS Code with Flutter extensions
- Xcode (for iOS development on macOS)
-
Clone the repository
git clone https://github.com/yourusername/ConnectX.git cd ConnectX -
Install dependencies
flutter pub get
-
Generate code (for JSON serialization)
flutter pub run build_runner build --delete-conflicting-outputs
-
Create environment files
Create
.envfiles in the root directory:.env.development# API Configuration API_BASE_URL=https://reqres.in/api API_KEY=reqres-free-v1 API_VERSION=v1 # App Configuration APP_NAME=ConnectX Dev APP_VERSION=1.0.0 ENVIRONMENT=development # Feature Flags ENABLE_LOGGING=true ENABLE_ANALYTICS=false ENABLE_CRASHLYTICS=false SHOW_FLAVOR_BANNER=true # Performance CACHE_DURATION_HOURS=1 ITEMS_PER_PAGE=10 MAX_RETRY_COUNT=3 CONNECTION_TIMEOUT_SECONDS=30
.env.staging# API Configuration API_BASE_URL=https://reqres.in/api API_KEY=reqres-free-v1 API_VERSION=v1 # App Configuration APP_NAME=ConnectX Staging APP_VERSION=1.0.0 ENVIRONMENT=staging # Feature Flags ENABLE_LOGGING=true ENABLE_ANALYTICS=true ENABLE_CRASHLYTICS=false SHOW_FLAVOR_BANNER=true # Performance CACHE_DURATION_HOURS=1 ITEMS_PER_PAGE=10 MAX_RETRY_COUNT=3 CONNECTION_TIMEOUT_SECONDS=30
.env.production# API Configuration API_BASE_URL=https://reqres.in/api API_KEY=reqres-free-v1 API_VERSION=v1 # App Configuration APP_NAME=ConnectX APP_VERSION=1.0.0 ENVIRONMENT=production # Feature Flags ENABLE_LOGGING=false ENABLE_ANALYTICS=true ENABLE_CRASHLYTICS=true SHOW_FLAVOR_BANNER=false # Performance CACHE_DURATION_HOURS=24 ITEMS_PER_PAGE=10 MAX_RETRY_COUNT=3 CONNECTION_TIMEOUT_SECONDS=30
-
Run the app
Development:
flutter run -t lib/main_development.dart --flavor development
Staging:
flutter run -t lib/main_staging.dart --flavor staging
Production:
flutter run -t lib/main_production.dart --flavor production
When you modify model classes with @JsonSerializable() annotation:
# Watch mode (auto-regenerate on file changes)
flutter pub run build_runner watch
# One-time build
flutter pub run build_runner build --delete-conflicting-outputs# Analyze code
flutter analyze
# Format code
dart format lib/
# Run tests
flutter test- Create feature directory under
lib/features/ - Implement data layer (models, data sources, repository)
- Implement domain layer (entities, use cases, repository interface)
- Implement presentation layer (BLoC, pages, widgets)
- Register dependencies in
core/di/dependency_injection.dart - Add routes in
app/router/app_router.dart
LoadUsersEvent- Load initial usersLoadMoreUsersEvent- Load next page (pagination)SearchUsersEvent- Search users with debouncingClearSearchEvent- Clear search and restore listLoadUserDetailEvent- Load single user detailsRefreshUsersEvent- Pull-to-refreshRetryEvent- Retry failed operationResetUserDetailEvent- Navigate back from detail
UserInitialState- Initial stateUserLoadingState- Loading indicatorUsersLoadedState- Users loaded successfullyUserDetailLoadingState- Loading user detailUserDetailLoadedState- User detail loadedUserSearchResultsState- Search resultsUserEmptyState- No results foundUserErrorState- Error with retry option
The app uses the ReqRes API for demonstration purposes.
Endpoints used:
GET /users?page={page}&per_page={perPage}- Get paginated usersGET /users/{id}- Get user details
- Network Failures:
NetworkFailure,ConnectionFailure,TimeoutFailure - Server Failures:
ServerFailure,UnauthorizedFailure,NotFoundFailure - Cache Failures:
CacheFailure,CacheExpiredFailure - Parse Failures:
JsonParseFailure,DataParseFailure - User Failures:
UserNotFoundFailure,UsersLoadFailure
- Automatic retry with exponential backoff
- Max 3 retry attempts (configurable)
- Manual retry button on error state
- Preserves last event for intelligent retry
Three flavors are configured:
| Flavor | Purpose | Logging | Analytics | Banner |
|---|---|---|---|---|
| Development | Local development | Enabled | Disabled | Shown |
| Staging | QA/Testing | Enabled | Enabled | Shown |
| Production | Release | Disabled | Enabled | Hidden |
Key environment variables:
API_BASE_URL- Base URL for APIAPI_KEY- API authentication keyENVIRONMENT- Current environmentENABLE_LOGGING- Enable/disable loggingCACHE_DURATION_HOURS- Cache expiry durationITEMS_PER_PAGE- Pagination sizeCONNECTION_TIMEOUT_SECONDS- HTTP timeout
# Development APK
flutter build apk -t lib/main_development.dart --flavor development
# Staging APK
flutter build apk -t lib/main_staging.dart --flavor staging
# Production APK
flutter build apk -t lib/main_production.dart --flavor production --release
# Production App Bundle
flutter build appbundle -t lib/main_production.dart --flavor production --release# Development
flutter build ios -t lib/main_development.dart --flavor development
# Production
flutter build ios -t lib/main_production.dart --flavor production --release# Run all tests
flutter test
# Run tests with coverage
flutter test --coverage
# View coverage report
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html- Image Caching: All user avatars are cached using
cached_network_image - Lazy Loading: Infinite scroll with pagination
- Debouncing: Search queries debounced to 500ms
- Memory Management: Efficient state updates using
copyWith - HTTP Caching: Response caching with expiry
- Connection Pooling: Reusable HTTP connections via Dio
Custom logging system with multiple levels:
AppLogger.debug('Debug message');
AppLogger.info('Info message');
AppLogger.warning('Warning message');
AppLogger.error('Error message', error: e, stackTrace: st);Log levels controlled via ENABLE_LOGGING environment variable.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Effective Dart guidelines
- Use meaningful variable and function names
- Write comments for complex logic
- Maintain consistent formatting (use
dart format) - Write unit tests for business logic
Issue: Build runner fails
# Solution: Clean and rebuild
flutter clean
flutter pub get
flutter pub run build_runner build --delete-conflicting-outputsIssue: Environment variables not loading
# Solution: Ensure .env files exist in root directory
# Check file names match: .env.development, .env.staging, .env.productionIssue: DI registration error
# Solution: Ensure all dependencies are registered in dependency_injection.dart
# Check initialization order (external -> core -> data -> domain -> presentation)This project is licensed under the MIT License - see the LICENSE file for details.
- ReqRes API - Free API for testing
- Flutter - UI framework
- BLoC Library - State management
- Clean Architecture principles by Robert C. Martin
For questions or support, please open an issue on GitHub.
Built with Flutter 💙