Flutter Firebase Setup: Connect Android, iOS, and Web

Coding Liquids blog cover featuring Sagnik Bhattacharya for Flutter Firebase Setup: Connect Android, iOS, and Web, with flutterfire cli and flutterfire configure, firebase_core and generated firebase_options.dart, and firebase.initializeapp before runapp.
Coding Liquids blog cover featuring Sagnik Bhattacharya for Flutter Firebase Setup: Connect Android, iOS, and Web, with flutterfire cli and flutterfire configure, firebase_core and generated firebase_options.dart, and firebase.initializeapp before runapp.

The setup sequence is easiest to verify while flutterfire configure and Firebase initialisation run live.

Subscribe on YouTube@codingliquids

Understand what FlutterFire wires together

firebase_core starts the native Firebase SDK using options that identify the project and platform app. The generated options are public identifiers, while security comes from Authentication, rules, App Check, and server controls.

Initialising the wrong project can send development data into production even when the app compiles.

flutter pub add firebase_core

Register every platform application

Create a Firebase project, then register Android package names, Apple bundle identifiers, and the web app independently. Those identifiers must match the Flutter platform projects exactly, including case and build flavour suffixes.

Reusing a configuration file from another bundle produces confusing service and analytics behaviour.

dependencies:
  flutter:
    sdk: flutter
  firebase_core: any

An Instagram setup matrix pairs each Firebase identifier with its Android, Apple, or web configuration point.

Follow me on Instagram@sagnikteaches

Generate firebase_options.dart with FlutterFire CLI

Install or update Firebase CLI and FlutterFire CLI, sign in, then run flutterfire configure from the Flutter root. Select the project and target platforms so the tool writes lib/firebase_options.dart and platform configuration.

Editing generated option constants by hand makes the next configure run overwrite local fixes.

The Complete Flutter Guide course thumbnail

Build production-ready Firebase Setup features

The Complete Flutter Guide turns firebase setup into maintainable app architecture, polished UI, and testable production code.

Enrol now

Bring firebase_core and the generated options into main.dart before calling Firebase.initializeApp.

import 'package:firebase_core/firebase_core.dart';

Initialise Firebase before runApp

Ensure widget binding exists and await Firebase.initializeApp with DefaultFirebaseOptions.currentPlatform. Only construct repositories that use Firebase after the returned Future completes.

Calling a Firebase product before initialisation triggers core no-app or not-initialized errors.

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const MaterialApp(home: Scaffold(body: Text('Firebase ready'))));
}

Finish Android iOS and web platform setup

Android needs a matching google-services configuration and supported minSdk, while iOS needs the plist and successful CocoaPods integration. Web receives its values from the generated options and must use the correct authorised domains for Authentication.

A successful Dart compile does not prove Gradle, pods, entitlements, or web origins are configured.

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  assert(Firebase.app().options.projectId == 'my-staging-project');
  runApp(const MyApp());
}

My LinkedIn configuration notes examine flavours, project isolation, and the risk of a valid connection to the wrong backend.

Connect on LinkedInSagnik Bhattacharya
The Complete Flutter Guide course thumbnail

The Complete Flutter Guide: Build Android, iOS and Web apps

Go from scratch to building industry-standard apps with Riverpod, Firebase, animations, REST APIs, and more.

Enrol now

Prove the configured app at runtime

Read Firebase.app().options.projectId after initialisation and compare it with the expected environment in a debug assertion. A lightweight product call in a development build can confirm network and rules setup without writing production data.

Testing only the default app object cannot reveal that Firestore rules deny the intended operation.

dart pub global activate flutterfire_cli
flutterfire configure
flutter pub add firebase_core

Diagnose setup errors by layer

duplicate-app means the same named app was initialised twice, missing options points to configuration, and Gradle or pod failures are native build issues. Clean only the affected build tooling after checking identifiers and generated files first.

Repeatedly deleting caches cannot correct a wrong bundle ID or an unselected FlutterFire platform.

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  assert(Firebase.app().options.projectId == 'my-staging-project');
  runApp(const MaterialApp(home: Scaffold(body: Center(child: Text('Firebase ready')))));
}

Keep separate Firebase projects for development and production, then run flutterfire configure for the intended environment rather than swapping project IDs in source. A debug assertion can compare Firebase.app().options.projectId with the selected flavour. This catches a valid but wrong configuration—the most dangerous setup error because every API call succeeds against the wrong backend.

Verify each platform with concrete evidence

Start the configuration from a clean working tree so generated changes are easy to inspect. The Android application ID in Gradle must exactly match the Firebase Android app, including a flavour suffix such as .dev. Apple uses the bundle identifier selected by the active Xcode configuration, and each shipped identifier needs its own registered app. After flutterfire configure, inspect firebase_options.dart and the platform project changes, but do not copy values between environments by hand.

Several familiar messages point to distinct layers. [core/no-app] No Firebase App '[DEFAULT]' has been created means product code ran before successful initialisation. Default FirebaseApp is not initialized on Android usually deserves the same ordering check plus confirmation that the selected build variant has matching configuration. An iOS pod or module error belongs to CocoaPods and Xcode integration, while an Authentication auth/unauthorized-domain response means the web origin must be allowed in the Firebase console. Deleting every cache conceals these differences and rarely repairs a mismatched identifier.

Flavoured applications should make project selection explicit. Generate or maintain separate option entry points for development, staging, and production, select one from the compile-time environment, and assert its projectId in debug builds. Use separate Firebase projects when test data, rules, functions, or analytics must not touch production. A valid API key is not a secret and does not replace Firestore rules, Storage rules, Authentication controls, or App Check.

Prove the setup on a real build of every target rather than relying on hot restart. Launch from a terminated state, await Firebase.initializeApp, read the expected project ID, and perform one harmless product operation against a development backend. Android release signing can differ from debug signing, Apple capabilities may vary by target, and a deployed web hostname differs from localhost. Record the platform, app identifier, project ID, and initialisation result in non-sensitive diagnostics. That small matrix catches the dangerous case where Firebase works perfectly against the wrong project.

Continuous integration should fail early when generated configuration is absent or belongs to an unexpected project. Pass the intended flavour into the build, check that its options file exists, and run a small startup test without printing keys. When Android reports that no matching client was found for a package name, compare the active applicationId with the registered Firebase app rather than editing Dart. When Apple reports an invalid or missing plist relationship, inspect target membership and the active scheme. Web deployments should add the real hostname to authorised domains and test the deployed origin, because localhost success cannot validate production redirects.

Team onboarding becomes safer when the repository documents who owns each Firebase project, which billing account it uses, and how developers obtain permitted access. The setup guide should never instruct people to share a personal login or commit a service-account credential. Client configuration may be public; administrative credentials are not.

Common mistakes

  • Understand what FlutterFire wires together: In FlutterFire configuration, initialising the wrong project can send development data into production even when the app compiles; inspect this FlutterFire configuration cause before changing another FlutterFire configuration widget.
  • Register every platform application: In FlutterFire configuration, reusing a configuration file from another bundle produces confusing service and analytics behaviour; inspect this FlutterFire configuration cause before changing another FlutterFire configuration widget.
  • Generate firebase_options.dart with FlutterFire CLI: In FlutterFire configuration, editing generated option constants by hand makes the next configure run overwrite local fixes; inspect this FlutterFire configuration cause before changing another FlutterFire configuration widget.
  • Initialise Firebase before runApp: In FlutterFire configuration, calling a Firebase product before initialisation triggers core no-app or not-initialized errors; inspect this FlutterFire configuration cause before changing another FlutterFire configuration widget.
  • Finish Android iOS and web platform setup: In FlutterFire configuration, a successful Dart compile does not prove Gradle, pods, entitlements, or web origins are configured; inspect this FlutterFire configuration cause before changing another FlutterFire configuration widget.
  • Prove the configured app at runtime: In FlutterFire configuration, testing only the default app object cannot reveal that Firestore rules deny the intended operation; inspect this FlutterFire configuration cause before changing another FlutterFire configuration widget.

Frequently asked questions

How does understand what FlutterFire wires together work in FlutterFire configuration?

For FlutterFire configuration, the starting rule is that firebase_core starts the native Firebase SDK using options that identify the project and platform app. Apply this FlutterFire configuration rule first because understand what FlutterFire wires together determines whether the FlutterFire configuration pattern fits.

Why does generate firebase_options.dart with FlutterFire CLI matter for FlutterFire configuration?

In FlutterFire configuration, select the project and target platforms so the tool writes lib/firebase_options.dart and platform configuration. Keeping generate firebase_options.dart with FlutterFire CLI at the FlutterFire configuration call site exposes the FlutterFire configuration return value directly.

What failure should I test first in FlutterFire configuration?

First reproduce the FlutterFire configuration case where a successful Dart compile does not prove Gradle, pods, entitlements, or web origins are configured. Evidence from Android, iOS, and web must then show the expected project identifier and one successful development-backend operation.

How can I verify FlutterFire configuration before release?

Exercise diagnose setup errors by layer with real FlutterFire configuration inputs on every shipped platform. Inspect the final FlutterFire configuration callback or output; a successful FlutterFire configuration button tap alone is not proof.

Further reads

Connect FlutterFire configuration to the surrounding Flutter stack through these published tutorials:

Sources: FlutterFire and Firebase documentation; FlutterFire configuration examples verified against current stable Flutter.