Loading repository data…
Loading repository data…
gregertw / repository
Starter app for Flutter that includes many different production app features; some not typically included in demo apps.
Maintainer: Greger Wedel, https://github.com/gregertw
Latest update: Support for Flutter 3.29.2
There are lots of simple Flutter app examples out there, but very few show how to tie together the elements you need to put an app into production. In my process of evaluating Flutter maturity and readiness for production apps, I started to put together the various elements into a single app. It evolved over time to a starter app (and template on Github) that has been updated and following best practices and sound engineering practices.
The focus of this starter app is thus not on the UI or functionality, but rather to show how a set of typical app functionalities can be developed and supported in a sound code structure. The app structure has also been designed to support a development team through separation of concerns and sound abstractions, as well as support for all layers of testing (unit, widget, and integration).
This app has the following elements:
Here is a blog post about the value of using a starter app: https://stuff.greger.io/2021/08/why-and-how-you-should-use-a-flutter-starter-app.html
Also, see my blog post for a more detailed introduction to the various features: https://stuff.greger.io/2019/07/production-quality-flutter-starter-app.html.
I'm happy to accept pull requests for any improvements that will make this starter app even more complete from a production app point of view. Here are some possible improvements:
See CHANGELOG.md
The easiest way to get started with this app is to get it running in your own browser locally. To do that, you need to configure a Google OAuth2 application at https://console.cloud.google.com/apis/credentials. You need to define your own application so you can use Google to log in, and you need to make sure that the app knows about the URL it is running from (i.e. localhost:port), so that it can present the URL to Google and the Google app is configured with the same URL as an allowed redirect URL. In addition, the app needs to present the secret for the Google app you have configured. If there is a mismatch in the URL your app is running under, what is configured in the app, and what is configured for the Google app, the login process will fail.
Here are the steps:
clientIdGoogleApp in lib/environment.dartsecretGoogleWebin the same fileflutter run --debug --web-port=50000 (this will allow the app to present the right redirect URL)In Visual Studio Code, you can add an entry to launch.json in .vscode:
{
"name": "Flutter: Debug web",
"type": "dart",
"request": "launch",
"args": [
"--web-port=50000"
],
"flutterMode": "debug",
"program": "lib/main.dart"
},
The app uses a Google Firebase project (though this is not a requirement if you drop analytics, messaging, and crashlytics). The currently configured test project is available for your testing, but obviously you will not be able to log into these projects, so the value of that is just that you can test the app without doing any code changes. To start tinkering, you will want to create your own Firebase project.
But, first of all, check out the actingweb_firstapp code base (it's a template!). You can use any editor.
Make sure you have available a device to run the app on, either a physical device or an emulator, then just run it on an emulator. You should be able to log into the app with your Google account (only on emulator, not web, see later). Github is not supported for web, and requires a secret that Google does not require, so it will not work until you register your own Github OAuth2 client.
lib/environment.dart contains the client values for Github and Google, here you can add your own client id and secrets when you register your app for authentication with each of these.
See further below for introductions on specific areas of the app's functionality.
Even if this app comes out of the box functionally working, you need to make it your own to build on it. As a minimum, you need to do the following:
android/app/src/main/AndroidManifest.xml and ios/Runner/AppDelegate.swift to update your API
key for Google Maps (see https://cloud.google.com/maps-platform/)That's all you need! The below sections give you more details on how each of the services have been integrated in the code base.
There are two integration needs in a Flutter app: integrate towards the underlying platform and integrating towards the various external services you may want to use. Examples of the first is location, mobile messaging services (which has support built into the iOS and Android platforms), persistence of data (i.e. shared_preferences), and registration of URI schemes for your application, so that your application can receive the authentication code necessary as part of authentication. The second category is how to use Google Firebase services (analytics, messaging, and crash reports), authentication using OAuth2 towards e.g. Github and Google, or Google Maps to show the map of where you are.
The most difficult is typically the integration towards the underlying platforms, but as Flutter has evolved with support for web and matured on iOS and Android, more and more of integration necessary can be done in the Dart code and the platform specific configuration has been reduced.
But still, you will need API keys or client ids or URLs for where to connect, and this must be configured somewhere. In /lib/environment.dart you will find a class that pickes configuration variables from the environment (which can be set in your CI/CD pipeline) and where you can set defaults. However, these can only be used in the Dart code, so where there are needs for underlying platform integration (in ios, android, and web directories), you will have to go in and edit the code and configs there directly. How is documented in the sections below.
NOTE!! This is only for the web version of the app
To build the web version, use flutter build web --base-href="/<some_path>/" or use just /if you deploy to the root of
the domain. The web app should be deployed to https://my.domain.com/some_path/.
As of Flutter 2, web is supported on stable release, https://flutter.dev/web and a web version of app is available at https://gregertw.github.io/actingweb_firstapp_web. The support for packagaes has increased, and most of the functionality is now supported in the web version.
See https://flutter.dev/docs/get-started/web. If you get errors, do flutter clean.
Firebase has now better web support as well, but there are two areas where you need to configure in the web/ folder: for Firebase messaging to work and for Google Maps.
For Google Maps, see https://pub.dev/packages/google_maps_flutter_web. You need an API key and add a script to index.html.
Your Firebase project (google.com) must be configured with a web app (under General settings). The config script snippet you get from setting up the web must replace the Firebase app config in web/firebase-messaging-sw.js:
var firebaseConfig = {
apiKey: "AIzaSyDjVjlcUKYUBb62x4K8WUGI47mXXlfKTtI",
authDomain: "actingweb-firstapp.firebaseapp.com",
databaseURL: "https://actingweb-firstapp.firebaseio.com",
projectId: "actingweb-firstapp",
storageBucket: "actingweb-firstapp.appspot.com",
messagingSenderId: "748007732162",
appId: "1:748007732162:web:ff42373829ce3137785c5b",
measurementId: "G-M7F2YR6FNW"
};
If you have used the Firebase CLI tool to create a firebase_options.dart, you will find your Firebase web API key in apiKey attribute. Add it also in lib/environment.dart (you don't need manual configuration in index.html anymore). This is according to the documentation as it should be used in the getToken() method.
You can find all the details at https://firebase.flutter.dev/docs/messaging/overview, and you can find more details on Firebase and messaging below.
The kIsWeb global variable is used to detect if the app is running on web and made available in appstate.dart as a isWeb bool that can be used across the app. The variable is also used in appstate.dart to do the correct Firebase Messaging initialisation.
If you are doing debugging of the app on web, use Google login, you need to edit environment.dart with the client id
and secret, and then (for local debugging) edit auth.dart and oauth.js with the localhost redirect URL with port number.
In addition, the Google web app (credentials) also need the http://localhost:<portnumber>/ configured as a legal redirect URL. Configure Google web app at https://console.cloud.google.com/apis/credentials.
Note on Github! Github only supports clientid and secret, and does explicitly not support retrieving an access token from a web applications (it is blocked with no CORS headers). This is because it is not considered safe. This means that Github auth is disabled on web.
The authentication in first_app has been refactored three times. This last time, a package called oauth2_client has been used as it has support for iOS, Android, and web. Previously, flutter_appauth was used, but the mai