How to Connect Flutter With Firebase
How to Connect Flutter With Firebase Firebase is Google’s comprehensive backend platform designed to help developers build high-quality mobile and web applications without managing infrastructure. When combined with Flutter — Google’s open-source UI toolkit for crafting natively compiled applications for mobile, web, and desktop from a single codebase — developers gain a powerful, scalable, and ef
How to Connect Flutter With Firebase
Firebase is Google’s comprehensive backend platform designed to help developers build high-quality mobile and web applications without managing infrastructure. When combined with Flutter — Google’s open-source UI toolkit for crafting natively compiled applications for mobile, web, and desktop from a single codebase — developers gain a powerful, scalable, and efficient solution for modern app development. Connecting Flutter with Firebase unlocks access to essential services such as authentication, real-time databases, cloud storage, analytics, push notifications, and more — all with minimal configuration and seamless integration.
This tutorial provides a complete, step-by-step guide on how to connect Flutter with Firebase, covering everything from project setup to advanced implementation. Whether you’re building your first Flutter app or scaling an existing one, understanding how to integrate Firebase correctly ensures performance, security, and long-term maintainability. By the end of this guide, you’ll have a fully functional Flutter application connected to Firebase services, equipped with best practices and real-world examples to guide your development.
Step-by-Step Guide
Step 1: Set Up a Firebase Project
To begin, you need a Firebase project. Navigate to the Firebase Console and sign in with your Google account. Click on “Add project” to create a new one. Provide a project name — for example, “FlutterFirebaseApp” — and proceed through the setup wizard. You may optionally enable Google Analytics, but it’s not required for basic functionality.
Once the project is created, you’ll be redirected to the project overview page. Here, you’ll see options to add apps for Android, iOS, or web. Since Flutter supports multiple platforms, you’ll need to register each target platform individually.
Step 2: Register Your Flutter App with Firebase
For Android:
- Click on the Android icon under “Add app.”
- Enter your Flutter app’s package name. You can find this in the file
android/app/src/main/AndroidManifest.xml. Look for thepackageattribute in the manifest tag. - Provide an app nickname (optional) and click “Register app.”
- Download the
google-services.jsonfile and place it in theandroid/appdirectory of your Flutter project.
For iOS:
- Click on the iOS icon under “Add app.”
- Enter your iOS bundle ID. You can find this in
ios/Runner/Info.plistunder theCFBundleIdentifierkey. - Download the
GoogleService-Info.plistfile and place it inside theios/Runnerfolder of your Flutter project. - Open Xcode, right-click on the Runner folder, and select “Add Files to ‘Runner’.” Choose the downloaded
GoogleService-Info.plistfile and ensure “Copy items if needed” is checked.
For Web:
- Click on the Web icon under “Add app.”
- Register your app and copy the provided Firebase configuration object (it includes apiKey, authDomain, projectId, etc.).
- Save this configuration for later use in your Flutter web code.
Step 3: Configure Android Project
After placing the google-services.json file in the correct directory, you need to configure the Android build files.
First, open the project-level android/build.gradle file and ensure you have the Google Services classpath in the dependencies block:
dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'com.google.gms:google-services:4.3.15'
}
Next, open the app-level android/app/build.gradle file and add the following line at the very bottom of the file:
apply plugin: 'com.google.gms.google-services'
These configurations enable the Firebase SDK to read the configuration file during the build process and initialize Firebase services correctly on Android.
Step 4: Configure iOS Project
For iOS, you need to add the Firebase SDK using CocoaPods. Open your terminal and navigate to the ios directory of your Flutter project:
cd ios
Then, run:
pod install
If you don’t have CocoaPods installed, install it using:
sudo gem install cocoapods
After running pod install, you’ll see a Podfile.lock and an xcworkspace file. From now on, always open your project using the .xcworkspace file in Xcode, not the .xcodeproj file.
Additionally, ensure that your iOS deployment target is set to at least iOS 11.0. Open the ios/Runner.xcworkspace file in Xcode, select the Runner project, go to the “General” tab, and set “Deployment Info” → “Deployment Target” to 11.0 or higher.
Step 5: Add Firebase Dependencies to Flutter
Now, return to your Flutter project root directory and open the pubspec.yaml file. Add the core Firebase packages you intend to use. For a basic setup, include:
dependencies:
flutter:
sdk: flutter
firebase_core: ^2.24.0
firebase_auth: ^4.15.0
cloud_firestore: ^4.8.0
firebase_storage: ^11.6.0
firebase_messaging: ^14.6.10
firebase_analytics: ^10.5.0
Save the file and run:
flutter pub get
This downloads and installs all the Firebase plugins. Each package serves a specific purpose:
- firebase_core: Initializes Firebase in your Flutter app.
- firebase_auth: Handles user authentication (email/password, Google, Facebook, etc.).
- cloud_firestore: Provides access to Firebase’s NoSQL document database.
- firebase_storage: Enables file uploads and downloads to Firebase Cloud Storage.
- firebase_messaging: Enables push notifications via FCM (Firebase Cloud Messaging).
- firebase_analytics: Tracks user behavior and app usage metrics.
Step 6: Initialize Firebase in Your Flutter App
Before using any Firebase service, you must initialize Firebase in your app. Open your main Dart file (usually lib/main.dart) and update it as follows:
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Firebase App',
theme: ThemeData(primarySwatch: Colors.blue),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Firebase Connected')),
body: const Center(child: Text('Firebase is successfully connected!')),
);
}
}
Key points:
WidgetsFlutterBinding.ensureInitialized()ensures Flutter is ready before initializing Firebase.Firebase.initializeApp()is an asynchronous function — it must be awaited before rendering the UI.- Place this initialization code at the top of your
main()function, beforerunApp().
If you’re building for the web, you also need to initialize Firebase with the web configuration. Open web/index.html and paste the Firebase configuration script from the Firebase console into the <head> section:
<script>
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT.firebaseapp.com",
projectId: "YOUR_PROJECT",
storageBucket: "YOUR_PROJECT.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
</script>
Then, in your Flutter web app, Firebase will automatically detect the web configuration. No additional code is needed in Dart.
Step 7: Implement Firebase Authentication
Authentication is one of the most common use cases for Firebase. Let’s implement email/password authentication.
First, enable Email/Password sign-in method in the Firebase Console:
- Go to the Firebase Console → Authentication → Sign-in method.
- Enable “Email/Password” and click “Save.”
Now, update your main.dart to include a login form:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final FirebaseAuth _auth = FirebaseAuth.instance;
void _signIn() async {
if (_formKey.currentState!.validate()) {
try {
await _auth.signInWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
Navigator.pushReplacementNamed(context, '/home');
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.toString()}')),
);
}
}
}
void _signUp() async {
if (_formKey.currentState!.validate()) {
try {
await _auth.createUserWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
Navigator.pushReplacementNamed(context, '/home');
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.toString()}')),
);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Login / Sign Up')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value == null || value.length < 6) {
return 'Password must be at least 6 characters';
}
return null;
},
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: _signIn,
child: const Text('Sign In'),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: _signUp,
child: const Text('Sign Up'),
),
],
),
),
),
);
}
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
}
Add a home screen to redirect to after login:
class HomePage extends StatelessWidget {
final FirebaseAuth _auth = FirebaseAuth.instance;
void _signOut() async {
await _auth.signOut();
Navigator.pushReplacementNamed(context, '/login');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
TextButton(
onPressed: _signOut,
child: const Text('Logout'),
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You are logged in!', style: TextStyle(fontSize: 20)),
const SizedBox(height: 20),
Text('User: ${_auth.currentUser?.email ?? 'Unknown'}'),
],
),
),
);
}
}
Finally, update your MaterialApp routes:
MaterialApp(
title: 'Flutter Firebase App',
theme: ThemeData(primarySwatch: Colors.blue),
initialRoute: '/login',
routes: {
'/login': (context) => const LoginPage(),
'/home': (context) => const HomePage(),
},
)
Step 8: Use Cloud Firestore for Data Storage
Cloud Firestore is a flexible, scalable NoSQL cloud database. Let’s store user profile data after registration.
First, enable Firestore in the Firebase Console:
- Go to Firestore → Create database.
- Select “Start in test mode” (for development only) → Click “Enable.”
Now, update the sign-up function to write user data to Firestore:
void _signUp() async {
if (_formKey.currentState!.validate()) {
try {
UserCredential userCredential = await _auth.createUserWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
// Write user data to Firestore
await FirebaseFirestore.instance.collection('users').doc(userCredential.user!.uid).set({
'email': _emailController.text.trim(),
'createdAt': FieldValue.serverTimestamp(),
'displayName': _emailController.text.split('@')[0],
});
Navigator.pushReplacementNamed(context, '/home');
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.toString()}')),
);
}
}
}
To read user data in the home screen:
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Map<String, dynamic>? _userData;
@override
void initState() {
super.initState();
_loadUserData();
}
void _loadUserData() async {
final user = _auth.currentUser;
if (user != null) {
DocumentSnapshot snapshot = await _firestore.collection('users').doc(user.uid).get();
if (snapshot.exists) {
setState(() {
_userData = snapshot.data() as Map<String, dynamic>?;
});
}
}
}
void _signOut() async {
await _auth.signOut();
Navigator.pushReplacementNamed(context, '/login');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
TextButton(
onPressed: _signOut,
child: const Text('Logout'),
),
],
),
body: _userData == null
? const Center(child: CircularProgressIndicator())
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Welcome!', style: TextStyle(fontSize: 20)),
const SizedBox(height: 20),
Text('Email: ${_userData?['email']}'),
Text('Display Name: ${_userData?['displayName']}'),
Text('Joined: ${_userData?['createdAt']?.toString().split(' ')[0]}'),
],
),
),
);
}
}
Step 9: Add Firebase Storage for File Uploads
Firebase Storage allows you to upload and store user-generated files such as images, videos, or documents. Let’s add an image upload feature.
First, enable Firebase Storage in the Firebase Console:
- Go to Storage → Get Started.
- Select “Start in test mode” → Click “Enable.”
Add the image_picker package to your pubspec.yaml:
dependencies:
image_picker: ^1.0.4
Run flutter pub get.
Now, update your HomePage to include an upload button:
import 'package:image_picker/image_picker.dart';
import 'package:firebase_storage/firebase_storage.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseStorage _storage = FirebaseStorage.instance;
final ImagePicker _picker = ImagePicker();
File? _selectedImage;
String? _downloadUrl;
void _pickImage() async {
final XFile? pickedFile = await _picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_selectedImage = File(pickedFile.path);
});
}
}
void _uploadImage() async {
if (_selectedImage == null) return;
final String fileName = DateTime.now().millisecondsSinceEpoch.toString();
final Reference ref = _storage.ref().child('images/$fileName.jpg');
final UploadTask uploadTask = ref.putFile(_selectedImage!);
TaskSnapshot snapshot = await uploadTask;
_downloadUrl = await snapshot.ref.getDownloadURL();
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
TextButton(
onPressed: _signOut,
child: const Text('Logout'),
),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
if (_userData != null)
Text('Welcome, ${_userData?['displayName']}'),
const SizedBox(height: 20),
if (_selectedImage != null)
Image.file(_selectedImage!, height: 200, fit: BoxFit.cover),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _pickImage,
child: const Text('Pick Image'),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: _uploadImage,
child: const Text('Upload Image'),
),
const SizedBox(height: 16),
if (_downloadUrl != null)
Image.network(_downloadUrl!, height: 150, fit: BoxFit.cover),
],
),
),
);
}
}
Best Practices
Secure Your Firebase Rules
By default, Firebase services operate in test mode, allowing unrestricted access. This is acceptable during development but dangerous in production. Always lock down your rules.
For Firestore, update rules in the Firebase Console → Firestore → Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
This ensures users can only read and write their own documents.
For Firebase Storage:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images/{imageId} {
allow read, write: if request.auth != null;
}
}
}
Always validate file types, sizes, and ownership in your rules to prevent abuse.
Use Environment Variables for Configuration
Never hardcode Firebase API keys or credentials in your Dart files. Use environment variables or configuration files.
Create a lib/config/firebase_config.dart:
class FirebaseConfig {
static const String apiKey = 'YOUR_API_KEY';
static const String authDomain = 'YOUR_PROJECT.firebaseapp.com';
static const String projectId = 'YOUR_PROJECT';
static const String storageBucket = 'YOUR_PROJECT.appspot.com';
static const String messagingSenderId = 'YOUR_SENDER_ID';
static const String appId = 'YOUR_APP_ID';
}
Then initialize Firebase with:
await Firebase.initializeApp(
options: FirebaseOptions(
apiKey: FirebaseConfig.apiKey,
appId: FirebaseConfig.appId,
messagingSenderId: FirebaseConfig.messagingSenderId,
projectId: FirebaseConfig.projectId,
storageBucket: FirebaseConfig.storageBucket,
authDomain: FirebaseConfig.authDomain,
),
);
This keeps your configuration centralized and easier to manage across environments.
Handle Authentication State Responsively
Use authStateChanges() to listen for real-time authentication changes:
StreamSubscription<User?> _authStateSubscription;
@override
void initState() {
super.initState();
_authStateSubscription = FirebaseAuth.instance.authStateChanges().listen((User? user) {
if (user == null) {
Navigator.pushReplacementNamed(context, '/login');
} else {
Navigator.pushReplacementNamed(context, '/home');
}
});
}
@override
void dispose() {
_authStateSubscription.cancel();
super.dispose();
}
This ensures your UI updates automatically when users log in or out, even if they close and reopen the app.
Optimize Network Requests and Caching
Enable Firestore offline persistence for better UX:
await FirebaseFirestore.instance.settings(
persistenceEnabled: true,
cacheSizeBytes: FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED,
);
This allows your app to read and write data even when offline, syncing later when connectivity resumes.
Use Firebase App Check for Security
App Check helps protect your backend resources from abuse by ensuring requests come from your authentic app. Enable App Check in the Firebase Console and integrate the package:
dependencies:
firebase_app_check: ^0.2.0+1
Initialize it in your main function:
await FirebaseAppCheck.instance.activate(
webRecaptchaSiteKey: 'your-recaptcha-site-key',
);
Minimize Dependencies and Tree-Shake
Only import the Firebase packages you need. Avoid importing the entire Firebase SDK. For example, if you only use authentication and Firestore, don’t include firebase_messaging or firebase_analytics unless necessary. This reduces app size and improves startup time.
Tools and Resources
Essential Flutter Firebase Packages
- firebase_core – Core initialization library.
- firebase_auth – User authentication.
- cloud_firestore – Real-time NoSQL database.
- firebase_storage – File storage service.
- firebase_messaging – Push notifications (FCM).
- firebase_analytics – User behavior tracking.
- firebase_performance – App performance monitoring.
- firebase_crashlytics – Real-time crash reporting.
- firebase_remote_config – Dynamic feature toggles and configurations.
- firebase_app_check – Bot and abuse protection.
Development Tools
- Firebase Console – Central dashboard to manage all Firebase services.
- Flutter DevTools – Debug and profile your app performance and memory usage.
- Android Studio / VS Code – IDEs with excellent Flutter and Firebase plugin support.
- Postman or Insomnia – For testing REST APIs if you use Firebase Functions.
- FlutterFire CLI – Command-line tool to automate Firebase project setup.
Documentation and Learning Resources
- FlutterFire Documentation – Official Flutter + Firebase guides.
- Firebase Documentation – Comprehensive Firebase service guides.
- Firebase YouTube Channel – Tutorials and live demos.
- Flutter Codelabs – Hands-on coding labs from Google.
- FlutterFire GitHub Repository – Source code and issue tracking.
Third-Party Tools
- FlutterFlow – No-code Flutter builder with Firebase integration.
- Supabase – Open-source Firebase alternative for those seeking self-hosted options.
- AppWrite – Self-hosted backend platform with similar features to Firebase.
Real Examples
Example 1: Social Media App with Authentication and Posts
Imagine building a microblogging app similar to Twitter. Users sign in with email or Google, post text updates, and like other users’ posts.
- Authentication: Firebase Auth with Google sign-in.
- Posts: Stored in Firestore under the
postscollection with fields:userId,content,timestamp,likes. - Likes: Stored in a subcollection
posts/{postId}/likesto track which users liked a post. - Real-time updates: Use
StreamBuilderto listen to Firestore queries and update UI instantly. - Images: Uploaded to Firebase Storage, with URLs stored in the post document.
Example 2: Task Manager with Offline Support
A productivity app where users create, edit, and complete tasks.
- Offline-first: Firestore persistence enabled so tasks are saved locally even without internet.
- Sync: Data automatically syncs when connection resumes.
- Notifications: Firebase Cloud Messaging sends reminders when a task is due.
- Analytics: Firebase Analytics tracks how often users open the app and complete tasks.
Example 3: E-commerce App with Real-time Inventory
An app that sells products with real-time stock tracking.
- Products: Stored in Firestore with fields like
name,price,stock. - Inventory updates: When a user purchases an item, the app decrements stock atomically using Firestore transactions.
- Images: Stored in Firebase Storage with CDN delivery for fast loading.
- Push notifications: Notify users when out-of-stock items are back in inventory.
FAQs
Why is my Flutter app crashing on startup with Firebase?
Most commonly, this is due to missing or misconfigured Firebase configuration files. Double-check that:
google-services.jsonis inandroid/appfor Android.GoogleService-Info.plistis inios/Runnerfor iOS.- You’ve added the Google Services plugin to
android/app/build.gradle. - You’ve run
pod installin theiosdirectory.
Can I use Firebase without Google Play Services on Android?
Firebase relies on Google Play Services for many features (like FCM and App Check). On devices without Google Play Services (e.g., Huawei devices), some services may not work. Use firebase_messaging with FCM for Android, but consider using alternative push services like Huawei Push Kit or Apple APNs for iOS.
How do I handle Firebase authentication errors?
Always wrap Firebase Auth calls in try-catch blocks. Common errors include:
EmailAlreadyInUse– User already exists.InvalidEmail– Email format is invalid.WeakPassword– Password too short or lacks complexity.UserNotFound– No account found with that email.WrongPassword– Incorrect password.
Use e.code to identify the error type and show user-friendly messages.
Do I need to pay to use Firebase with Flutter?
Firebase offers a generous free tier for most apps. You can build and launch a full-featured app without paying. Costs only apply if you exceed quotas for storage, bandwidth, or number of operations. Monitor usage in the Firebase Console under “Billing.”
Can I use Firebase with Flutter Web?
Yes. Firebase fully supports Flutter Web. You must initialize Firebase in your web/index.html file with the web configuration, and use the same Dart packages as mobile. All services — Auth, Firestore, Storage, etc. — work identically on web.
How do I test Firebase in development?
Use Firebase Emulator Suite to simulate services locally:
- Install the Firebase CLI:
npm install -g firebase-tools - Run:
firebase init emulators - Select services to emulate (Auth, Firestore, Storage, etc.).
- Start emulators:
firebase emulators:start - In your Flutter app, add:
FirebaseAppCheck.instance.activate(...)and setdebugTokenduring development.
What’s the difference between Firebase Realtime Database and Cloud Firestore?
- Realtime Database is a JSON tree structure with real-time sync. Simpler but less flexible for complex queries.
- Cloud Firestore is a document-based NoSQL database with powerful querying, indexing, and scalability. Recommended for most new Flutter apps.
Conclusion
Connecting Flutter with Firebase is a transformative step for any mobile or web developer aiming to build scalable, secure, and feature-rich applications without managing backend infrastructure. This tutorial has walked you through every critical phase — from setting up a Firebase project and configuring platform-specific files to implementing authentication, real-time data storage, file uploads, and security rules.
By following best practices such as securing your rules, using environment variables, enabling offline persistence, and minimizing dependencies, you ensure your app performs reliably and scales efficiently. Real-world examples demonstrate how Firebase powers everything from social networks to e-commerce platforms, proving its versatility and robustness.
Remember: Firebase is not a one-size-fits-all solution, but when paired with Flutter’s cross-platform capabilities, it becomes an exceptionally powerful combination. As your app grows, continue exploring advanced Firebase features like Cloud Functions, Remote Config, and Crashlytics to enhance functionality and user experience.
Start small, test thoroughly, and iterate. With the foundation laid in this guide, you’re now equipped to build production-ready Flutter applications powered by Firebase — efficiently, securely, and at scale.