A Flutter project template built with BLoC pattern and Clean Architecture principles. This project is configured with three environments (development, staging, production) for both mobile and web platforms.
This project follows Clean Architecture principles:
- Presentation Layer: UI components, BLoC files
- Domain Layer: Use cases, entities, repository interfaces
- Data Layer: Repository implementations, data sources, models
The project uses .env files for configuring different environments:
.env.development- Development settings.env.staging- Staging settings.env.production- Production settings
The application's environment is determined by the entry point file used when running or building the app:
lib/main_dev.dart- Development environmentlib/main_stag.dart- Staging environmentlib/main_prod.dart- Production environment
The Android flavors are configured in android/app/build.gradle with three product flavors:
flavorDimensions "environment"
productFlavors {
dev {
dimension "environment"
applicationIdSuffix ".dev"
resValue "string", "app_name", "Base Project Dev"
}
stag {
dimension "environment"
applicationIdSuffix ".stag"
resValue "string", "app_name", "Base Project Stag"
}
prod {
dimension "environment"
resValue "string", "app_name", "Base Project"
}
}For iOS, you need to set up Xcode schemes manually:
-
Open the Runner.xcworkspace in Xcode:
open ios/Runner.xcworkspace
-
Create three new schemes for each environment:
- Xcode → Product → Scheme → New Scheme...
- Create schemes named: Runner-dev, Runner-stag, Runner-prod
-
Configure each scheme:
- In Xcode, select a scheme → Edit Scheme...
- Under 'Build Configuration', select 'Debug' for development and staging, 'Release' for production
- Under 'Arguments', add environment variables:
- For Runner-dev:
FLAVOR=dev - For Runner-stag:
FLAVOR=stag - For Runner-prod:
FLAVOR=prod
- For Runner-dev:
-
Update Info.plist by adding custom display names for each flavor:
- Add the key
CFBundleDisplayNamewith value:$(PRODUCT_NAME)-$(FLAVOR)
- Add the key
# Development
flutter run --flavor dev -t lib/main_dev.dart
# Staging
flutter run --flavor stag -t lib/main_stag.dart
# Production
flutter run --flavor prod -t lib/main_prod.dart# Development
flutter run -d chrome -t lib/main_dev.dart
# Staging
flutter run -d chrome -t lib/main_stag.dart
# Production
flutter run -d chrome -t lib/main_prod.dart# Development APK
flutter build apk --flavor dev -t lib/main_dev.dart
# Staging APK
flutter build apk --flavor stag -t lib/main_stag.dart
# Production APK
flutter build apk --flavor prod -t lib/main_prod.dart# Development AAB
flutter build appbundle --flavor dev -t lib/main_dev.dart
# Staging AAB
flutter build appbundle --flavor stag -t lib/main_stag.dart
# Production AAB
flutter build appbundle --flavor prod -t lib/main_prod.dart# Development build
flutter build web -t lib/main_dev.dart
# Staging build
flutter build web -t lib/main_stag.dart
# Production build
flutter build web --release -t lib/main_prod.dartWhen deploying web builds, each environment should have its own deployment:
- Deploy development build to development server/URL
- Deploy staging build to staging server/URL
- Deploy production build to production server/URL
- Generate code with build_runner:
flutter pub run build_runner build --delete-conflicting-outputs- Before committing code, run the analyzer:
flutter analyzeThis project uses the following major dependencies:
- flutter_bloc: State management
- get_it: Dependency injection
- dio: HTTP client
- shared_preferences: Local storage
- flutter_dotenv: Environment configuration
- intl: Internationalization support
- intl_utils: Internationalization utilities
This project uses the intl package for internationalization support. The following guide explains how to generate and use locales in the project.
The localization files are organized as follows:
lib/
core/
locale/
l10n/ # ARB files for each language
intl_en.arb # English translations
intl_vi.arb # Vietnamese translations
generated/ # Generated localization files
- Add new translation keys to
lib/core/locale/l10n/intl_en.arb:
{
"newKey": "English text",
"@newKey": {
"description": "Description of the translation"
}
}- Add corresponding translations to
lib/core/locale/l10n/intl_vi.arb:
{
"newKey": "Vietnamese text",
"@newKey": {
"description": "Description of the translation"
}
}- For translations with parameters, use the following format:
{
"welcomeMessage": "Welcome to {appName}!",
"@welcomeMessage": {
"description": "Welcome message with app name",
"placeholders": {
"appName": {
"type": "String"
}
}
}
}Run the following command to generate the localization files:
flutter pub run intl_utils:generateThis will generate the necessary files in the lib/core/locale/generated directory.
// Using the generated S class
Text(S.of(context).appTitle)
// Using with parameters
Text(S.of(context).welcomeMessage('My App'))
// Using error messages
Text(S.of(context).errorMessage('Connection failed'))// Get current translations
final translations = S.current;
// Use translations with parameters
final welcomeMessage = translations.welcomeMessage('My App');
final errorMessage = translations.errorMessage('Connection failed');class MyCubit extends Cubit<MyState> {
void showError(String error) {
// Using translations in cubit
final message = S.current.errorMessage(error);
// Use the message...
}
}class ApiService {
void handleError(dynamic error) {
// Using translations in service
final message = S.current.serverError;
// Use the message...
}
}| Key | English | Vietnamese |
|---|---|---|
| appTitle | Base Project | Dự án cơ sở |
| homeScreenTitle | Home Screen | Màn hình chính |
| settingsLabel | Settings | Cài đặt |
| Key | English | Vietnamese |
|---|---|---|
| themeSettings | Theme Settings | Cài đặt giao diện |
| lightTheme | Light Theme | Giao diện sáng |
| darkTheme | Dark Theme | Giao diện tối |
| systemTheme | System Theme | Giao diện hệ thống |
| Key | English | Vietnamese |
|---|---|---|
| languageSettings | Language Settings | Cài đặt ngôn ngữ |
| english | English | Tiếng Anh |
| vietnamese | Vietnamese | Tiếng Việt |
| Key | English | Vietnamese |
|---|---|---|
| welcomeMessage | Welcome to {appName}! | Chào mừng đến với {appName}! |
| errorMessage | An error occurred: {error} | Đã xảy ra lỗi: {error} |
| successMessage | Operation completed successfully | Thao tác hoàn tất thành công |
| loadingMessage | Loading... | Đang tải... |
| Key | English | Vietnamese |
|---|---|---|
| retryButton | Retry | Thử lại |
| cancelButton | Cancel | Hủy |
| saveButton | Save | Lưu |
| deleteButton | Delete | Xóa |
| editButton | Edit | Sửa |
| Key | English | Vietnamese |
|---|---|---|
| searchHint | Search... | Tìm kiếm... |
| noResultsFound | No results found | Không tìm thấy kết quả |
| Key | English | Vietnamese |
|---|---|---|
| networkError | Network error occurred | Lỗi kết nối mạng |
| serverError | Server error occurred | Lỗi máy chủ |
| connectionError | Connection error occurred | Lỗi kết nối |
| timeoutError | Request timed out | Yêu cầu đã hết thời gian chờ |
- Create a new ARB file in
lib/core/locale/l10n/(e.g.,intl_es.arbfor Spanish) - Copy all translation keys from
intl_en.arb - Translate all values to the new language
- Run
flutter pub run intl_utils:generate - Add the new locale to
LocaleCubit.supportedLocales
- Always use the generated
Sclass for translations - Keep translation keys descriptive and organized
- Use parameters for dynamic content
- Add descriptions for all translation keys
- Maintain consistent naming conventions
- Test translations in all supported languages
- Keep translations up to date with UI changes