π₯ welcome to Flutter Huevo.
Watch/star this repo to be notified when updates are pushed.
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.
There are 3 ways to get started: Template, Fork, and Cherry-Pick.
Best if you want to start a new project from scratch with all the SFA features included. And you don't care about keeping your project up to date with the SFA repo.
To get started with Option 1: Template, click the green "Use this template" button above.
Best if you want to start a new project from scratch with all the SFA features included. And you want to keep your repo up to date with the SFA repo.
To get started with Option 2: Fork, fork the repo and follow the instructions below.
Best if you have an existing project and want to manually pick the SFA features you want. Or if you want better control over what features you want.
To get started with Option 3: Cherry-Pick simply use this GitHub repo as a guide.
And cherry-pick (copy & paste) the features and files you want to use into your own project.
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
For a detailed developer guide with architecture diagrams (layer flow, DI, navigation, feature layout, and app-backend relationship), see App Architecture.
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