Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
74f2294
fix: browser run
koniz-dev Dec 6, 2025
7e165b7
fix: remove asset unused
koniz-dev Dec 6, 2025
d6621fa
chore: Update Android build configuration and conditionally apply Goo…
koniz-dev Dec 7, 2025
3a07c19
chore: Simplify Google Services plugin application and add configurat…
koniz-dev Dec 7, 2025
aa3233a
chore: Add Google Services plugin to build configuration
koniz-dev Dec 7, 2025
7c4cfcc
chore: Update Java toolchain version in build configuration
koniz-dev Dec 7, 2025
7474d69
chore: Enable toolchain auto-provisioning and add Foojay resolver plugin
koniz-dev Dec 7, 2025
602d215
chore: Configure Java home for Gradle daemon to use Java 21
koniz-dev Dec 7, 2025
050e011
chore: Configure Java toolchain for subprojects and apply Google Serv…
koniz-dev Dec 7, 2025
b2c8db1
chore: Refactor project evaluation dependencies for Google Services i…
koniz-dev Dec 7, 2025
437a3ba
chore: Update Firebase configuration in google-services.json
koniz-dev Dec 7, 2025
30c5c6d
chore: Conditionally apply Google Services plugin for Firebase libraries
koniz-dev Dec 7, 2025
29c6b0d
chore: Move Google Services plugin application to after android block…
koniz-dev Dec 7, 2025
8fac764
chore: Force early initialization of Google Services plugin in build …
koniz-dev Dec 7, 2025
2d901bd
chore: Remove early initialization logic for Google Services plugin
koniz-dev Dec 7, 2025
47c1f1a
chore: Downgrade Google Services plugin version for compatibility
koniz-dev Dec 7, 2025
c6163fc
feat: Add comprehensive deployment documentation, configure Android b…
koniz-dev Dec 7, 2025
5d450fc
feat: Update Firebase dependencies, migrate Android build to Kotlin D…
koniz-dev Dec 7, 2025
f668ba1
docs: Add comprehensive deployment, monitoring, analytics, and gettin…
koniz-dev Dec 7, 2025
af6ee77
feat: Add initial Android build.gradle.kts configuration for Flutter …
koniz-dev Dec 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ app.*.symbols
# Obfuscation related
app.*.map.json

# Google Services
google-services.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ lib/

### Prerequisites

- Flutter SDK (>=3.0.0)
- Dart SDK (>=3.0.0)
- Flutter SDK (>=3.27.0)
- Dart SDK (>=3.8.0)
- Android Studio / VS Code with Flutter extensions
- Xcode (for iOS development on macOS)

Expand Down Expand Up @@ -219,7 +219,8 @@ lib/
1. **Rename the project** (if needed) - Update package name from `flutter_starter` to your project name
2. **Configure your environment** - See [Configuration System](#-configuration-system) below
3. **Set up Firebase** (optional) - For remote feature flags and performance monitoring
- Add `google-services.json` (Android) and `GoogleService-Info.plist` (iOS)
- **Setup Firebase Config**: Add `google-services.json` (Android) and `GoogleService-Info.plist` (iOS).
> **Note**: These files are gitignored for security. You must add them manually for local development. For CI/CD, use environment variables to generate them.
- Initialize Firebase in your app
4. **Customize the theme** - Edit `lib/shared/theme/app_theme.dart`
5. **Explore example features** - Check out `lib/features/` for examples:
Expand Down
2 changes: 2 additions & 0 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ android {
flutter {
source = "../.."
}

apply(plugin = "com.google.gms.google-services")
24 changes: 19 additions & 5 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
plugins {
id("com.android.application") version "8.11.1" apply false
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
id("com.google.gms.google-services") version "4.3.15" apply false
}

allprojects {
repositories {
google()
mavenCentral()
}
}

val newBuildDir: Directory =
rootProject.layout.buildDirectory
.dir("../../build")
.get()
val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
rootProject.layout.buildDirectory.value(newBuildDir)

subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)

afterEvaluate {
if (project.plugins.hasPlugin("java") || project.plugins.hasPlugin("com.android.library")) {
project.extensions.findByType<JavaPluginExtension>()?.apply {
toolchain { languageVersion.set(JavaLanguageVersion.of(17)) }
}
}
}
}

subprojects {
project.evaluationDependsOn(":app")
if (project.name != "app") {
project.evaluationDependsOn(":app")
}
}

tasks.register<Delete>("clean") {
Expand Down
4 changes: 4 additions & 0 deletions android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
# Enable toolchain auto-provisioning
org.gradle.java.installations.auto-download=true
# Use Java 21 from Android Studio for Gradle daemon (to compile build scripts)
org.gradle.java.home=C:\\Program Files\\Android\\Android Studio\\jbr
4 changes: 3 additions & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
2 changes: 2 additions & 0 deletions android/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.11.1" apply false
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
id("com.google.gms.google-services") version "4.3.15" apply false
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}

include(":app")
3 changes: 2 additions & 1 deletion docs/deployment/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ firebase deploy --only hosting
1. **Add Dependencies** to `pubspec.yaml`:
```yaml
dependencies:
firebase_core: ^3.0.0
firebase_core: ^2.24.2
firebase_crashlytics: ^4.0.0
```

Expand Down Expand Up @@ -477,6 +477,7 @@ void main() async {
3. **Configure Firebase Projects**:
- Create Firebase projects for each environment
- Add `google-services.json` (Android) and `GoogleService-Info.plist` (iOS)
- **Note:** These files are gitignored. For CI/CD (e.g., GitHub Actions), store them as Base64 secrets (`ANDROID_GOOGLE_SERVICES_JSON`, `IOS_GOOGLE_SERVICE_INFO`) and decode them during the build process.
- Place in appropriate flavor directories

### Analytics Integration
Expand Down
2 changes: 1 addition & 1 deletion docs/deployment/monitoring-analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Update `pubspec.yaml`:

```yaml
dependencies:
firebase_core: ^3.0.0
firebase_core: ^2.24.2
firebase_crashlytics: ^4.0.0
```

Expand Down
15 changes: 0 additions & 15 deletions docs/guides/onboarding/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,6 @@

This guide will help you set up your development environment and get the Flutter Starter project running.

## Prerequisites

Before you begin, ensure you have the following installed:

- **Flutter SDK**: Version 3.0.0 or higher
- Check your version: `flutter --version`
- Install/update: [Flutter Installation Guide](https://docs.flutter.dev/get-started/install)

- **Dart SDK**: Version 3.0.0 or higher (included with Flutter)

- **IDE**: Choose one of the following:
- **VS Code** (recommended): Install Flutter and Dart extensions
- **Android Studio**: Install Flutter and Dart plugins
- **IntelliJ IDEA**: Install Flutter and Dart plugins

- **Platform-specific tools** (for your target platforms):
- **Android**: Android Studio with Android SDK
- **iOS**: Xcode (macOS only)
Expand Down
68 changes: 22 additions & 46 deletions lib/core/config/env_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import 'package:flutter_dotenv/flutter_dotenv.dart';

/// Environment configuration loader with fallback chain:
/// 1. .env file (for local development)
/// 2. --dart-define flags (for CI/CD)
/// 3. Default values
/// 2. Default values
///
/// Note: --dart-define flags are compile-time only and cannot be accessed
/// dynamically at runtime. They must be accessed via const
/// String.fromEnvironment() for specific known keys if needed.
///
/// Usage:
/// ```dart
Expand All @@ -20,7 +23,7 @@ class EnvConfig {
/// This should be called before runApp() in main.dart
///
/// The .env file is optional. If it doesn't exist, the system will fall back
/// to --dart-define flags or default values.
/// to default values.
///
/// Note: For .env to be loaded, it must be added to pubspec.yaml assets
/// after creating it from .env.example
Expand Down Expand Up @@ -50,13 +53,11 @@ class EnvConfig {

/// Get environment variable with fallback chain:
/// 1. .env file value (if loaded)
/// 2. --dart-define flag value
/// 3. Default value (if provided)
/// 2. Default value (if provided)
///
/// Parameters:
/// - [key]: The environment variable key
/// - [defaultValue]: Optional default value if not found in .env or
/// --dart-define
/// - [defaultValue]: Optional default value if not found in .env
///
/// Returns:
/// The environment variable value, or [defaultValue] if not found
Expand All @@ -78,17 +79,14 @@ class EnvConfig {
return value;
}
} on Exception {
// Variable not found in .env, continue to next priority
// Variable not found in .env, continue to default
}
}

// Priority 2: Check --dart-define flags
final dartDefineValue = String.fromEnvironment(key);
if (dartDefineValue.isNotEmpty) {
return dartDefineValue;
}

// Priority 3: Return default value
// Return default value
// Note: --dart-define flags are compile-time only and cannot be
// accessed dynamically at runtime. They must be accessed via
// const String.fromEnvironment() for specific known keys.
return defaultValue;
}

Expand All @@ -102,21 +100,11 @@ class EnvConfig {
try {
return dotenv.getBool(key, fallback: defaultValue);
} on Exception {
// Variable not found in .env, continue to next priority
// Variable not found in .env, continue to default
}
}

// Priority 2: Check --dart-define flags
final dartDefineValue = String.fromEnvironment(key);
if (dartDefineValue.isNotEmpty) {
final lowerValue = dartDefineValue.toLowerCase().trim();
return lowerValue == 'true' ||
lowerValue == '1' ||
lowerValue == 'yes' ||
lowerValue == 'on';
}

// Priority 3: Return default value
// Return default value
return defaultValue;
}

Expand All @@ -129,17 +117,11 @@ class EnvConfig {
try {
return dotenv.getInt(key, fallback: defaultValue);
} on Exception {
// Variable not found in .env, continue to next priority
// Variable not found in .env, continue to default
}
}

// Priority 2: Check --dart-define flags
final dartDefineValue = String.fromEnvironment(key);
if (dartDefineValue.isNotEmpty) {
return int.tryParse(dartDefineValue) ?? defaultValue;
}

// Priority 3: Return default value
// Return default value
return defaultValue;
}

Expand All @@ -152,23 +134,17 @@ class EnvConfig {
try {
return dotenv.getDouble(key, fallback: defaultValue);
} on Exception {
// Variable not found in .env, continue to next priority
// Variable not found in .env, continue to default
}
}

// Priority 2: Check --dart-define flags
final dartDefineValue = String.fromEnvironment(key);
if (dartDefineValue.isNotEmpty) {
return double.tryParse(dartDefineValue) ?? defaultValue;
}

// Priority 3: Return default value
// Return default value
return defaultValue;
}

/// Check if an environment variable exists
///
/// Returns true if the variable exists in .env file or --dart-define
/// Returns true if the variable exists in .env file
static bool has(String key) {
// Check .env file (if loaded)
if (_isInitialized) {
Expand All @@ -181,8 +157,8 @@ class EnvConfig {
// Variable not found in .env
}
}
// Check --dart-define flags
return String.fromEnvironment(key).isNotEmpty;
// Note: --dart-define values cannot be checked dynamically at runtime
return false;
}

/// Get all environment variables as a map
Expand Down
2 changes: 1 addition & 1 deletion macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import shared_preferences_foundation

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FirebaseRemoteConfigPlugin.register(with: registry.registrar(forPlugin: "FirebaseRemoteConfigPlugin"))
FLTFirebaseRemoteConfigPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseRemoteConfigPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
Expand Down
Loading