Flutter Huevo is a starter template for Flutter & Firebase apps.
It's designed to be scalable and easy to maintain. And should save you months of development time.
Always keep up to date:
- Flutter
- Cocoapods
- Firebase CLI
| Feature | Pro |
|---|---|
| Platforms: Android, iOS, web | ✅ |
| Scalable Architecture using flutter_bloc | ✅ |
| Navigation using go_router | ✅ |
| Scalable App Styling | ✅ |
| GitHub Actions - code and formatting check | ✅ |
| Responsive Design | ✅ |
| Profile Page | ✅ |
| Settings Page: sign out, app version... | ✅ |
| Legal: Terms, Policy, Data Deletion | ✅ |
| Google Fonts | ✅ |
| Sign in and Sign Up Pages | ✅ |
| Input Validators | ✅ |
| Cached network image | ✅ |
| Email Support | ✅ |
| Lifetime Updates | ✅ |
| Firebase Project Integration | ✅️ |
| Firebase Cloud Functions | ✅️ |
| Firebase Authentication | ✅ ️ |
| Firebase Remote Config | ✅ ️ |
| Firebase Crashlytics | ✅ ️ |
| Firebase Firestore | ✅ ️ |
| Firebase Analytics | ✅ |
| Firebase Hosting | ✅ |
| Firebase Storage | ✅️ |
| Google Sign In | ✅ ️ |
| Apple Sign In | ✅ ️ |
| Common Cubits | ✅ ️ |
| In App Purchases (RevenueCat) | ✅ ️ |
| App Store Review Request | ✅ ️ |
| Local Notifications | ✅ ️ |
| Remote Notifications (Firebase) | ✅ ️ |
| HTTP Requests (dio) | ✅ ️ |
| Local Storage | ✅ ️ |
| Permissions | ✅ ️ |
| Environments | ✅ ️ |
| Localization | ✅️ |
| Dark Mode | ✅ ️ |
| Connectivity check | ✅ ️ |
| Hive - local database | ✅ ️ |
| MixPanel - analytics | ✅ ️ |
| Android - Release Signing | ✅ ️ |
| Onboarding | ✅ ️ |
| Forgot Password | ✅ ️ |
| Send Feedback Message | ✅ ️ |
| Delete User Account | ✅ ️ |
| Get User Timezone | ✅ ️ |
| 🎉 BONUS: Scalable Firebase Backend Template | ✅ ️ |
Firebase Console project set up:
- Create a new Firebase project (if you don't already have one)
- Enable Firestore
- Enable Auth
- Enable Email/Password sign-in method
- Switch to Blaze plan (pay as you go)
- Enable Cloud Functions
- Enable Storage (if needed)
- Enable Hosting (if needed)
- Enable Remote Config (if needed)
If you're using Flutter web with Firebase Storage, you'll need to enable CORS:
If you want to deploy your Flutter web app:
- Run
firebase init - Select
Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys - Select your Firebase project
- Enter
build/webas the public directory - Enter
Yfor single-page app - Enter
Nfor automatic builds and deploys with GitHub Actions
After that's done, you can deploy your Flutter web app with:
flutter build web, thenfirebase deploy.
To set up Firebase in the /app project:
- Run
cd app - Run
flutterfire configurein the terminal - Select your Firebase project
- Select platforms you want to support (Android, iOS, web)
- If asked to update files, select
y(yes) - (if using Cloud Functions) update the region in
app/lib/core/firebase/cloud_functions_provider.dart:21
To set up Firebase in the /firebase project:
- (if using Cloud Functions) update the region in
firebase/functions/src/index.ts:10 - Run
cd firebase - Run
firebase loginin the terminal - Run
firebase projects:listto see your Firebase projects - Find your project ID (i.e.
your-project-id) - Run
firebase use <project-id>(i.e.firebase use your-project-idto set your Firebase project - Run
cd functions - Run
npm install - Run
cd .. - Run
firebase deployto deploy Firestore rules and Cloud Functions to your Firebase project
Here's how to set up Google Sign In:
Here's how to set up Apple Sign In:
Notifications on iOS require additional setup:
To integrate RevenueCat:
- Set up RevenueCat: https://www.revenuecat.com/docs/getting-started
- Update
_androidApiKeyand_iosApiKeyinapp/feature/payment/provider/revenue_cat_provider.dart - Update
Paywallinapp/feature/payment/model/paywall.dartto fit your needs - Update
PaywallPageinapp/feature/payment/ui/page/paywall_page.dartto fit your needs - Update
_ProviderDIto useRevenueCatProviderinstead ofMockPaywallProvider
To integrate Mixpanel:
- Set up Mixpanel: https://mixpanel.com
- Update
_mixpanelTokeninapp/lib/feature/analytics/provider/mixpanel_analytics_provider.dart
The code architecture is based on flutter_bloc architecture proposal.
There are 4 layers:
- UI (Flutter Widgets)
- BLoC (stateful business logic)
- Repository (high-level API)
- Provider (low-level implementation)
And there's only 1 communication rule that we must follow:
The layer can only call the one layer below it.
That means that:
- UI can only call BLoC
- BLoC can only call Repository
- Repository can only call Provider
- Provider can only call external services (Firebase, HTTP, etc.)
And we avoid same-layer communication (as it creates interdependencies):
UserRepositorycallingAuthRepositoryis not allowed.UserCubitcallingUserRepositoryandAuthRepositoryis allowed.
When creating Providers, Repositories, and Cubits we follow this rule:
- Providers are created top-level (so that they can be used in multiple Repositories)
- Repositories are created top-level (so that they can be used in multiple Cubits)
- Cubits are created in the router builder callbacks (so that they're accessible only where needed)
- Cubits that are used in multiple screens are created top-level
Styling is based on Google's Material Design.
App-wide styling is defined in core/app/style.dart and is easy to update.
Here's a quick tip on custom Widget params. There are 2 Widget param types:
- data (user, title, ...)
- style (colors, paddings, ...)
Our custom Widgets should only hava data params.
And the style should be done app-wide (in style.dart).
That way all of our UI is consistent and easy to update.
To change the font:
- Go to Google Fonts and select a font.
- Download the font files.
- Add the font files to
assets/fonts(remove the old ones). - Update
style.dartwith the new font (i.e.return GoogleFonts.rubikTextTheme(textTheme)).
Localized string files are in lib/l10n.
To remove a language, just remove it's .arb file.
To add a language, duplicate app_en.arb and rename it to app_xx.arb
(where xx is the language code). Then translate the strings.
- Create a keystore file (if you don't already have one):
keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA \
-keysize 2048 -validity 10000 -alias upload
- Create
app/android/key.propertiesfile with the following content:
storePassword=<password-from-previous-step>
keyPassword=<password-from-previous-step>
keyAlias=upload
storeFile=<keystore-file-location>
- To build the release bundle, run
flutter build appbundle
I've found that turning on these 2 settings in GitHub repo settings helps a lot:
Always suggest updating pull request branchesAutomatically delete head branches