- Overview
- Getting Started
- Change Package Name
- Architecture
- Running/Debugger
- Features
- Library / Dependency
- Modules
- Continuous Integration and Deployment
Flutter is Google's UI toolkit for building beautiful, natively compiled applications for mobile, web, desktop, and embedded devices from a single codebase.
This is a micro-framework for Flutter which is designed to help simplify developing apps. Every project provides a simple boilerplate to help you build apps easier.
This project is open source, we welcome any contributions.
Here are some things you need to prepare before this Boilerplate setup:
- Flutter SDK Stable (Latest Version) Install
- Android Studio Install
- Visual Studio Code (Optional) Install
- Dart and Flutter extensions:
To set up your project based on this boilerplate, you need to do some of the steps you need to do.
Here are the steps for setting up a Project with this Flutter-Works boilerplate:
Step 1:
In this step you need to download(cloning) the files from this repository to your local computer:
git clone https://github.com/NeoSOFT-Technologies/mobile-flutter.git
Or
git clone [email protected]/NeoSOFT-Technologies/mobile-flutter.git
Step 2:
The next step is to open the folder that has been downloaded / cloned into a cli application such
as bash
, cmd
, terminal
.
After cloning the repo and follow these steps to setup the project.
Each layer of the architecture is a separate flutter package. The template
uses melos
to manage all package and performing actions like
linting and running tests accross all packages. You can setup melos
from here.
Melos can be installed as a global package,
dart pub global activate melos
Sensitive information like api keys, credentials, etc should not be checked into git repos,
especially public ones. To keep such data safe the template uses app_secrets.dart
file. If you
want to run the app locally, you will need to create a new file app_secrets.dart
under lib/secrets
. To help with setting up the secrets file, the template
inclued a skeleton secrets file.
melos run get
melos run generate
bash app/scripts/setup-hooks.sh
Read the scripts documentation to learn about all the scripts used in the project.
By default package names:
com.app.flutter_template
To change the package name, simply search for all com.app.flutter_template
, then replace it with
the new package name, for example: com.mycompany.
.
The architecture of the template facilitates separation of concerns and avoids tight coupling
between it's various layers. The goal is to have the ability to make changes to individual layers
without affecting the entire app. This architecture is an adaptation of concepts
from Hexagonal
& The Clean Architecture
.
The architecture is separated into the following layers
The architecture is separated into the following layers
app
: All UI and state management elements like widgets, pages and view models.core
: Core business implementationinfrastructure
: Services provide access to external elements such as databases, apis, etc.database-floor
: Floor as the Database providernetwork-retrofit
: Retrofit as the Database provider
Each layer has a di
directory to manage Dependency Injection for that layer.
Read the dependency management documentation to learn about all the scripts used in the project.
The template comes with built-in support for 3 flavors. Each flavor uses a different main.dart
file.
- Dev -
main_dev.dart
- QA -
main_qa.dart
- Prod -
main_prod.dart
You can setup any environment specific values in the respective main.dart
files.
To run a specific flavor you need to specify the flavor and target file.
flutter run --flavor qa -t lib/entrypoints/main_qa.dart
To avoid specifying all the flags every time, use the run.sh
script
Read the scripts documentation to learn about all the scripts used in the project.
The layers core
and services provider
within infrastructure each have an model
directory.
app layer
: We consume the same models used from core/domain as domain wont change in the case of frontend apps.core/shared/lib/src/model
: Model classes for performing business logic manipulations. They act as an abstraction to hide the local and remote data models.infrastructure/servicename/model
: Respective service provider contains local models (data classes for the database) and remote models (data classes for the api).
In-order to hide generated files, navigate to Android Studio
-> Preferences
-> Editor
-> File Types
and paste the below lines under ignore files and folders
section:
*.config.dart;*.inject.summary;*.inject.dart;*.g.dart;
In Visual Studio Code, navigate to Preferences
-> Settings
and search for Files:Exclude
. Add
the following patterns:
** /*.inject.summary
**/
*
.inject.
dart
*
* /*.g.dart
- Hexagonal Clean Architecture
- Adhering to SOLID Principles
- Repository Pattern for code separations
- Dependency Injection
- Network Layer
- Data Layer
- Better Logging
- Automatic Error Handling
- Built-in support for 3
flavors
-dev
,qa
andprod
. - Unit & Integration Tests
- CI for build release
- Use SonarQube Analysis & generate reports
- Crashlytics/Analytics
- Theme Manager
- Localisation
- Routing/Navigations
- Responsive Framework
- Pre-commit Checks
- Dart Analysis
Flutter Lints
for linting.- Dart Fix
- Flutter Format
- Dependency Injection - Injectable & GetIt
- Network - Retrofit
- Database - Floor
- Reactive Caching and Data-binding Framework - RiverPod
- Bloc Framework - Bloc
- Code Analysis - SonarQube
- Crashlytics - Firebase
- Continuous Integration - Github Action
- Navigation
- Localisation - Flutter Intl
- Responsive Farmework
- [Exception/Error Handling] (https://github.com/faiyyazs/flutter-errors)
By default when you use this boilerplate, there are several modules that are installed automatically, here is a list of available modules:
Name | Description |
---|---|
app | A module containing boilerplate app view implementation |
core | A module containing core business implementation of the product which includes data,domain & shared modules |
dependency-injection | A module that contains classes to achieve DI across multiple modules based on injectable & getIt |
infrastructure | A module that includes all external data providers/adapters which are outbound adapters to core module/ports. Further includes database-floor & network-retrofit as external ports. |
localisation | A module containing translation data |
statemanagement-bloc | A module which contains bloc used as a state management tool. To be used with statemanagement-core |
statemanagement-core | A module which includes base classes required to support state management in flutter. |
statemanagement-riverpod | A module which contains riverpod used as a state management tool. To be used with statemanagement-core |
themes | A library that contains theme manager implementation |
The Flutter template comes with built-in support for CI/CD using Github Actions.
The CI
workflow performs the following checks on every pull request:
- Lints the code with
flutter analyze
. - Runs tests using
flutter test
. - Build the android app.
- Build the ios app.
The CD
workflow performs the following actions:
- Bump the build number by 1.
- Build a signed release apk.
Upload apk to the app center.- Upload apk as artifact to release tag.
Build a signed iOS app.Upload ipa to testflight.- Upload the ipa as an artifact to release the tag.
- Commit the updated version to git.
For the android CD workflow to run, we need to perform the following setup steps:
- Follow these instructions
to generate an upload keystore
. Note down the
store password
,key alias
andkey password
. You will need these in later steps. - Use
openssl
to convert thejks
file toBase64
.
openssl base64 < app_key.jks | tr -d '\n' | tee app_key_encoded.txt
- Store the
base64
output onGithub Secrets
with the key nameKEYSTORE
. - Save the
store password
in github secrets with the key nameRELEASE_STORE_PASSWORD
. - Save the
key alias
in github secrets with the key nameRELEASE_KEY_ALIAS
. - Save the
key password
in github secrets with the key nameRELEASE_KEY_PASSWORD
. - Create a distribution on app center and get the upload key. You can get it from appcenter.ms/settings.
- Save the app center upload key on github secrets with key name
APP_CENTER_TOKEN
.
For the IOS job in the cd.yml
to run, you first need to have a
valid Apple Developer Account.If you don't have it yet, please
create one before proceeding further
We will divide the guide into steps so that it is easier to understand
- Register your
Bundle ID
. You can view the official Flutter guide here
CAUTION: Apple doesn't allow underscore in the bundle identifier. Read about valid identifiers here
- Create an application on the AppStore Connect Portal. Check out the official guide here
- Create a
Distribution Certificate
for your machine locally once. You can refer to this guide. Download the.p12
file for use later. Remember the password used to create this certificate as we will need this later - Create a
Provisioning Profile
for yourBundle ID
you registered above. You can refer to this guide. Download the profile for use later.
-
In the following template
- Replace
BUNDLE ID
with yourBundle Identifier
(You got that already from Step 1) - Replace
PROVISIONING PROFILE NAME
with your Provisioning Profile Name (You already created one in Step 2, use that) - Replace
TEAM_ID
with your team id. Look at this answer on "How to find your Team ID"
- Replace
Click to View Template
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>generateAppStoreInformation</key>
<false />
<key>manageAppVersionAndBuildNumber</key>
<true />
<key>method</key>
<string>app-store</string>
<key>provisioningProfiles</key>
<dict>
<key>BUNDLE-ID</key>
<string>PROVISION PROFILE NAME</string>
</dict>
<key>signingCertificate</key>
<string>Apple Distribution</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true />
<key>teamID</key>
<string>TEAM_ID</string>
<key>uploadBitcode</key>
<false />
<key>uploadSymbols</key>
<true />
</dict>
</plist>
Create a new file called options.plist
and save the above contents in that file
- Read the official guide to create an app specific password and remember it(;P)
- The pipeline uses this password to upload an ipa to testflight
- Add the following keys to
Github Secrets
-
BUILD_CERTIFICATE_BASE64
: The base64 of the p12 file we generated(Step 2) -
P12_PASSWORD
: The password of the p12 certificate generated above in Step 2 -
BUILD_PROVISION_PROFILE_BASE64
: The provisioning profile in base64(Step 2) -
KEYCHAIN_PASSWORD
: The password used to store the keychain in the local keystore of the Github Runner(Any random value) -
IOS_PLIST
: The options.plist file needed to make an ipa out of the xcarchive generated by flutter(Step 3) -
APPSTORE_PASSWORD
: The password passed to altool to upload the ipa to the store(Step 4) -
To generate a base64 string, use the following command, replacing
FILENAME
with your filename
openssl base64 < FILENAME | tr -d '\n' | tee ENCODED_FILENAME.txt
- If the branches that you will be running CD on are protected, you will need to use
a
Personal Access Token (PAT)
to commit the version changes. - After creating the
PAT
, exclude the account that the token belongs to from thebranch protection rules
. - Save the token in github secrets and update the key name in the
cd.yml
file under eachcheckout
action. - Since our
CD
workflow is triggered on a push, and we create a new commit in the workflow itself, the commit message created by theCD
workflow includes[skip ci]
tag so that the workflow does not end up in an infinite loop.Read more about this here
If you do not plan to use the CD workflow on protected branches, you can remove the token part from the checkout actions.
Checklist of all upcoming enhancements .
Contributions are welcome from anyone and everyone. We encourage you to review the Guiding principles for contributing