Developed by Flow Labs 🚀
This starter kit was created to address the challenges of initializing a project. At Flow Labs, we identified recurring patterns when starting a project: state management, authentication, forms, alerts, snackbars, styles, authentication, users, rules and more. The idea behind this repository is to consolidate all the knowledge we’ve gained from building apps into a single resource.
This kit is not a "framework"; rather, it's a guide for initializing a project with useful tools, popular libraries, folder structures, widgets, and more. The key idea is flexibility: developers have the freedom to choose their preferred structure. The goal of this repository is to be a helpful starting point without imposing rigid constraints on developers.
WhatsApp.Video.2025-01-14.at.02.12.07.mp4
WhatsApp.Video.2025-01-16.at.03.39.25.mp4
- Android
- IOS
- Sign In
- Apple
- Sign In/Up Email-Password
- Email/Password
- Validate Email
- Forgot Password
- Reset Password
- Profile
- Locked Screen (Biometric)
- Preferences
- Language
- Theme
- Light
- Dark
- Delete User
- Local Notifications
- Push Notifications
- Schedule Push Notifications
- Listeners
- Notifications Screen
- Public Onboarding
- Emulators
- Export data
- Download Kit
- Firebase
- Install firebase CLI
- Create firebase projects
- Configuration services
- Authentication
- Apple
- Email and password
- Firebase Database
- Storage
- Functions
- Authentication
- Deploy
- Rules
- Flutter App
- Configuration initial project
- Install VGV project
- Add dependencies
- Copy the app_initial
- Set Firebase environments in the project
- Create the app
- Install the kit
- Configuration initial project
- Set platforms
- IOS
- Set BundleId
- Set Min Version iOS
- Add Permissions
- Sign in with Apple
- Sign in with Google
- Sign in with Facebook
- Set Bundle ID
- Set Bundle ID (Alternative)
- Set env Info.plist
- Edit AppDelegate
- Set Push Notifications from Firebase
- Xcode
- Apple Developer and Firebase
- Biometric
- Android
- Set Namespace
- Update min-sdk-version
- Sign in with Google
- Sign in with Facebook
- Set Facebook keys
- Set Hashes and Package Name
- Set Hashes and Package Name (Alternative)
- Biometric config
- Config Schedule Notification
- Biometric
- IOS
- Emulators
- Export data from Firebase
- Firebase Auth
- Firestore
- Notifications
- Local
- Remote
This is the first step to do something with the kit
git clone https://github.com/Flowlabsio/flutter_starter_kit.git <project-name>
cd <project-name>
# Open project with vscode
code .
# Download CLI
curl -sL https://firebase.tools | bash
# Or from npm
npm install -g firebase-tools
# Login in firebase
firebase login
We will go to create the firebase projects for each environment
- Open
firebase/Makefile
and rename the varPROJECT_NAME
Clarification: If you will have more than three envirnments, add you other envirnments in the var ENVIRONMENTS
on firebase/Makefile
- Create the projects for each envirnments
cd firebase
make create_firebase_project
This command could be failed because the name is used on another project (and the names of the projects could be unique), if that happen try to run the next command for each failed project
firebase projects:create <project-name>-<env>
Or go to the console and drop the projects created and start again this process. Or create manually
This configuration is the basic setup to use the app_initial
this app use four services in Firabase, Authentication and Firestore Database, Storage and Functions

You must to cofig every services in each environment. Or if you want to only start with development
(or another) you can only set that and then the another environments
The Sign-in methods should be three
- Email and password (iOS and Android)
- Google (iOS and Android)
- Apple (iOS)

- Select "Google"

- Set enable and set the facing name (you can change this later)

You will see this title when you try to sign-in with Google in the app.

- Press "Save"

- Select "Apple"

- Press "Save"

Clarification: The Auth Emulator does not support facebook.com sign-in
- Create an app in Facebook console (
https://developers.facebook.com/
)
Clarification: You could create an app for environment

- Select the Auth service

- Select "I don’t want to connect a business portfolio yet."

- Go to App Settings -> Basic

- Copy the "App ID" and the "App secret"

- Go to Firebase Console and add Facebook provider in the Authentication service

- Paste the "App ID" and the "App secret", set enabled and press "Save"

- Press "Edit" facebook provider

- Copy the OAuth redirect link

- Go back to the Facebook dashboard, press "Use cases"

- Press "Customize"

- Select "Settings"

- Look the input "Valid OAuth Redirect URIs" and paste the OAuth redirect link from Firebase

- Select "Permissions"

- Look "email" and press "Add"

- Go to App Settings -> Basic (again)

- Got to App roles -> Roles

- Press "Add People"

- Add the user that are allow to use this service (facebook username). This user should have an facebook developer account

- Select "Email/Password"

- Press "Save"

- Enter in "Firebase Database" and press in "Create Database"

- Choose a location

- Press "Create"

Both Storage and Functions will need to set a "Billing Account". This point is important because if you dont do that you won't be able to use this services instead with the emulators
- Go to the "Storage" section and press "Upgrade project"

- If you have an account, choose one of them, otherwise, create one

- Set a budget

- After that you will see the button "Get started", press it

- Select your location

- Press "Create"

- Press "Get started"

- Press "Continue"

- Press "Finish"

Go to /firebase
and select the project firebase use <project-name>-<env>
Deploy the rules to Firebase
firebase deploy --only firestore:rules
firebase deploy --only storage
This starter kit use the template of Very Good Ventures to generate the app. The team believe it's a great standard to lunch an app. Therefore we will follow the next steps to install the CLI and generate the app.
- Install the VGV CLI
dart pub global activate very_good_cli
- Run one by one the commands to create the project and leave every file and file in the root folder
# Go to the root of the project
# Create the project
very_good create flutter_app <project-name>
# Copy project files
rsync -avh --ignore-existing <project-name>/ .
# Delete the other project
rm -rf <project-name>
flutter pub add app_ui --path=./kit/app_ui
flutter pub add app_core --path=./kit/app_core
flutter pub add app_helpers --path=./kit/app_helpers
flutter pub add freezed_annotation
flutter pub add dev:build_runner
flutter pub add dev:freezed
flutter pub add json_annotation
flutter pub add dev:json_serializable
flutter pub add dev:icons_launcher
flutter pub add go_router \
equatable \
flutter_native_splash \
reactive_forms \
google_sign_in \
sign_in_with_apple \
flutter_facebook_auth \
firebase_core \
firebase_auth \
cloud_firestore \
firebase_storage \
image_cropper \
image_picker \
permission_handler \
shared_preferences \
internet_connection_checker_plus \
device_info_plus \
firebase_messaging \
flutter_local_notifications \
timezone \
crypto \
smooth_page_indicator \
local_auth
And update the version
flutter pub upgrade --major-versions
- Delete the folders
rm -rf lib/app lib/counter test/counter
- Update
app_test.dart
echo "import 'package:flutter_test/flutter_test.dart';
void main() {
group('App', () {
testWidgets('', (tester) async {
expect(true, true);
});
});
}" > test/app/view/app_test.dart
- Replace localizations
rm -rf lib/l10n && mv kit/app_initial/lib/l10n lib/l10n
- Move the
kit/app_initial/lib/src
tolib/
cp -r kit/app_initial/lib/src lib/
- Go to
kit/app_initial/lib/bootstrap.dart.template
copy the content and paste inlib/bootstrap.dart
cp kit/app_initial/lib/bootstrap.dart.template lib/bootstrap.dart
- Run this command to fix the path's dependencies
./replace_text.sh ./lib "app_initial" "<project-name>"
flutter pub get
- Go to every
main_<env>
and fix theApp
dependencie
import 'package:<project-name>/src/app/app.dart';
- Delete the folder
kit/app_initial
rm -rf kit/app_initial
Before to start with this step remember to finish all the steps about create projects in the "Firebase" section
- Instal flutterfire_cli to config the firebase console with the app
dart pub global activate flutterfire_cli
- Then config run this command
./configure_firebase.sh \
--project="<project-name>-<env>" \
--ios-bundle-id="com.<org>.<project-name>.<env>" \
--android-package-name="com.<org>.<project-name>.<env>" \
--env="<env>"
- Set the platforms

If you go to

At the seccion "Your apps", you will see your apps

Will apear four new files in environments/<env>/
.
* firebase_options.dart
* GoogleService-Info.plist
* google-services.json
* firebase.json
After run the project with vscode, this files with be paste in their correct position
* lib/firebase_options.dart
* ios/Runner/GoogleService-Info.plist
* android/app/google-services.json
* firebase.json
Repeat this process for each environment (if you configurated the other environment).
-
From the root of the project run
make <env>
to paste the firebase config files in their positions (this proccess in automatic with vscode) -
Go to
lib/bootstrap.dart
and uncomment this lines
/// UNCOMMENT THIS LIKE AFTER ADDING FIREBASE CONFIGURATION
// await Firebase.initializeApp(
// options: DefaultFirebaseOptions.currentPlatform,
// );
- Delete old
.git
withrm -rf .git
- Open xcode
open ios/Runner.xcworkspace
- Press on "Runner"

- Go to "Signing & Capabilities"

- Set the bundle id and team for each team (remember that the bundle id must match with the bundle id create in firebase console)

In the Podfile
set the min version in 13
(required by firebase_auth). Go to ios/Podfile
, paste
platform :ios, '13.0'
In the Podfile
paste in the final
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
# You can remove unused permissions here
# for more information: https://github.com/BaseflowIT/flutter-permission-handler/blob/master/permission_handler/ios/Classes/PermissionHandlerEnums.h
# e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
## dart: PermissionGroup.camera
'PERMISSION_CAMERA=1',
## dart: PermissionGroup.microphone
'PERMISSION_MICROPHONE=1',
## dart: PermissionGroup.photos
'PERMISSION_PHOTOS=1',
## dart: PermissionGroup.notification
'PERMISSION_NOTIFICATIONS=1',
]
end
end
end
- Press on "Runner"

- Go to "Signing & Capabilities"

- Press

- Add "Sign in with Apple"

- Go to
environments/<env>/GoogleService-Info.plist
and copy the value of the keyREVERSED_CLIENT_ID
and past it in theenvironments/<env>/Info.plist
in theCFBundleURLSchemes
If you can't find the REVERSED_CLIENT_ID
it's because the Sign in with Google configuration in firabase is missing.
<dict>
<!-- Put me in the [my_project]/ios/Runner/Info.plist file -->
<!-- Google Sign-in Section -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<!-- TODO Replace this value: -->
<!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID -->
<string>[REVERSED_CLIENT_ID]</string>
</array>
</dict>
</array>
...
</dict>
- Go to
environments/<env>/GoogleService-Info.plist
and copy the value of the keyCLIENT_ID
and past it in theenvironments/<env>/env.json
in theGOOGLE_CLIENT_ID
{
...
"GOOGLE_CLIENT_ID": "<CLIENT_ID>",
...
}
- Go to App Settings -> Basic

- Scroll to the bottom of the page and press "Add platform"

- Select iOS

- Fill the Bundle ID and press "Save changes"

-
Go to https://developers.facebook.com/docs/facebook-login/ios
-
Select the app

- Add your Bundle ID and press "Save"

- Go to App Settings -> Basic

- Copy the
App Id
and go toenvironments/<env>/Info.plist
Replace the FACEBOOK_APP_ID
by the id (there are two places)
- Go to App Settings -> Advanced

- Copy the
Client token
and go toenvironments/<env>/Info.plist
Replace the FACEBOOK_CLIENT_TOKEN
by the token
- Replace the
FACEBOOK_DISPLAY_NAME
by the name what you want to show to the user
- Edit
application
method
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
GeneratedPluginRegistrant.register(with: self)
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
- Add import
import flutter_local_notifications
-
Open xcode
open ios/Runner.xcworkspace
-
Press Runner -> Signing & Capability

- Press "+ Capability"

- Add "Push Notifications"

- Press "+ Capability" again

- Add "Background Modes"

- Select "Background fetch" and "Remote notifications"

This key will use for testing and development environment. You can even use this key in another apps, but is not recommended because if you revoke the key, every app that use the key will lose the services
-
Go to Apple Developer (
https://developer.apple.com/account
) -
Go to "Keys"

- Add a new key and select the service "Apple Push Notifications service (APNs)"

- Download the key

- Go to Firebase console -> Project settings

- Go to "Cloud Messaging"

- Scroll down and set your key

Uncomment these lines in environments/<env>/Info.plist
<!-- Biometric -->
<!-- <key>NSFaceIDUsageDescription</key>
<string>The app requires access to Face ID</string> -->
<!-- Biometric -->
- Intall the next package
flutter pub add --dev change_app_package_name
- Run the command
dart run change_app_package_name:main com.<org>.<project-name> --android
Go to android/app/build.gradle
- Set
minSdkVersion
minSdkVersion 23
- Add
multiDexEnabled
android {
defaultConfig {
multiDexEnabled true
...
}
...
}
- Set
compileSdk
compileSdk 34
- Excecute
# Debug
keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android
- Copy the
SHA1
and go to the firebase console

- Go to "Project settings"

And select the android app

- Press in "Add fingerprint"

-
Paste the
SHA1
and press "Save" -
Update the environment files with the command
./configure_firebase.sh
(check the documentation about generate if you forgot the process)
- Go to
environments/<env>/AndroidManifest.xml
and uncomment the lines between<!-- Facebook -->
- Go to Facebook console and press App Settings -> Basic

- Copy the "App id"

-
Go to
environments/<env>/strings.xml
and paste in thefacebook_app_id
section -
Go to Facebook console, and press App Settings -> Advanced

- Copy the "Client token"

- Go to
environments/<env>/strings.xml
and paste in thefacebook_client_token
section
- Go to App Settings -> Basic

- Scroll to the bottom of the page and press "Add platform"

- Select Android

- Select the stores

- Fill inputs

To generate the hashes use (use password: "android"):
For development
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
For production
# Generate a keystore for porduction
keytool -genkeypair -v -keystore release-key.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias release-key
keytool -exportcert -alias release-key -keystore release-key | openssl sha1 -binary | openssl base64
After set every field press "Save"

-
Go to this link https://developers.facebook.com/docs/facebook-login/android/
-
Select the app

- Associate Your Package Name and Default Class

- Press "Save"

- Add the Key Hashes

To generate the hashes use:
For development
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
For production
keytool -exportcert -alias YOUR_RELEASE_KEY_ALIAS -keystore YOUR_RELEASE_KEY_PATH | openssl sha1 -binary | openssl base64
If you got this error

Copy that hash in the hashes list in Facebook Console
If you got this error
An internal error has occurred. Cleartext HTTP traffic to 10.0.2.2 not permitted
Go to AndroidManifest.xml
and this flags
<application
...
android:usesCleartextTraffic="true"
android:enableOnBackInvokedCallback="true"
...
>
-
Go to
android/app/src/main/kotlin/com/<org>/<project-name>/MainActivity.kt
-
Edit the
MainActivity.kt
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity: FlutterFragmentActivity() {
}
- Go to
environments/<env>/AndroidManifest.xml
and uncomment the lines between. Check themanifest
andapplication
context because there are two blocks
<!-- Schedule Notifications -->
...
<!-- Schedule Notifications -->
Uncomment these lines in environments/<env>/AndroidManifest.xml
<!-- Biometric -->
<!-- <uses-permission android:name="android.permission.USE_BIOMETRIC"/> -->
<!-- Biometric -->
To use the emulators, it's necessary to choose a real firebase project, use one of created before (recommended dev environment).
Clarification: If you want to use any service in the emulator, that service must be activated in the firebase project, for example "Google Sign In", the provider of google should be activated to use it in the emulator
To start the emulator run
cd firebase
firebase use <project-name>-<env>
firebase emulators:start --import export/ --export-on-exit export/
Install the function dependencies (if you want to use it)
cd firebase/functions
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
In the app, uncomment this lines in the bootstrap.dart
/// USE EMULATORS
FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080);
await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
await FirebaseStorage.instance.useStorageEmulator('localhost', 9199);
Clarification: There isn't a "native" way to export the data from firebase and insert in the emulator,
# Select the project
firebase use <project-name>-<env>
# Export data
firebase auth:export export/firebase_users.json --format=JSON --project <project-name>-<env>
- Install
firestore-export-import
npm install -g firestore-export-import
- You have to generate new private key from "Project Settings" from Firebase Console.

- Go to "Service Account" tab

- And press "Generate new private key"

-
Move the key
serviceAccountKey.json
to the folderfirebase/
-
Run
cd firebase
firestore-export -a ./<service-account-key>.json -b ./<data-namefile>.json
There is a class call LocalNotificationHelper
and that be able to send notifications. There is two types of notifications instant or scheduled. To use the instant notification call LocalNotificationHelper.instance.showNotification()
and for the scheduled .scheduleNotification()
. To remove a scheduled notification use .cancelNotification()
Also this class have three listeners
onBackgroundMessage
: This method is executed when the app receives a notification in killed or backgroundonMessage
: This method is executed when the app receives a notification in foregroundonMessageOpenedApp
: This method is executed when the app receives a notification and the user tap on it, a that open the app
To use the service there are many options (Firebase Cloud Messaging API, Cloud Functions, use your own service or third-party service with the server). This decision depends on the developer team and available resources. To test the remote push notification there is a function in Cloud Functions that send notifications to each device of a user. This service work in the emulator but remember active the service in Firebase Console. Every request to this service generate a notification document to the user in Firestore
From emulator
curl -X POST http://127.0.0.1:5001/<project-name>-<env>/<region>/send_notification \
-H "Content-Type: application/json" \
-d '{
"wheres": [
{"field": "id", "operator": "==", "value": "<user-id>"}
],
"data": {"key": "value"},
"title": "Title",
"body": "Body"
}'
From Firebase
curl -X POST https://<region>-<project-name>-<env>.cloudfunctions.net/send_notification \
-H "Content-Type: application/json" \
-d '{
"wheres": [
{"field": "id", "operator": "==", "value": "<user-id>"}
],
"data": {"key": "value"},
"title": "Title",
"body": "Body"
}'
Another option to test the remote notifications is with the offered service by Firebase. Find the FCM token in firestore users/{id}/devices/{id}
the attribute fcmToken

# Generate `coverage/lcov.info` file
flutter test --coverage
# Generate HTML report
# Note: on macOS you need to have lcov installed on your system (`brew install lcov`) to use this:
genhtml coverage/lcov.info -o coverage/html
# Open the report
open coverage/html/index.html
-
Open Xcode
-
Go to Runner -> Build Settings

- Filter by
FLAVOR_APP_NAME
. You will see the current names
