Irbisa · Cheatsheet
Firebase & Backend Services
FlutterFire setup, Auth, Firestore, FCM, Remote Config, Crashlytics, App Check, Supabase
How do you add Firebase to a Flutter app, and what must
main()await beforerunApp?// Once per machine: dart pub global activate flutterfire_cli// Once per project: flutterfire configureimport 'package:firebase_core/firebase_core.dart';import 'firebase_options.dart'; Future<void> main() async {…How do you read and write Firestore data in Flutter, and what is the difference between
get()andsnapshots()?final notes = FirebaseFirestore.instance .collection('notes') .withConverter<Note>( fromFirestore: (snap, _) => Note.fromJson(snap.data()!), toFirestore: (note, _) => note.toJson(), );…What is the difference between Cloud Firestore and Realtime Database, and when would you pick each?
How do you implement Google Sign-In with Firebase Auth, and why does it often work in debug but fail in the Play Store build?
Future<void> initGoogle() => GoogleSignIn.instance.initialize(); Future<UserCredential?> signInWithGoogle() async { if (kIsWeb) { return FirebaseAuth.instance.signInWithPopup(GoogleAuthProvider()); }…At cold start the app shows the login screen for a frame and then jumps to the feed. What is
authStateChanges()actually doing?class AuthGate extends StatelessWidget { const AuthGate({super.key}); @override Widget build(BuildContext context) { return StreamBuilder<User?>(…Your staging build writes to the production Firestore even though you swapped
firebase_options.dart. What is still pointing at prod?# One Firebase project per environment, one configure run per flavor.# repeat per build configuration (Release-staging, Profile-staging, ...)flutterfire configure --project=myapp-staging \ --out=lib/firebase/options_staging.dart \ --android-package-name=com.myapp.staging \ --android-out=android/app/src/staging/google-services.json \…A guest played for a week, then signed in with Google, and everything they had saved is gone. What did that sign-in do?
Future<void> startAsGuest() async { if (FirebaseAuth.instance.currentUser == null) { await FirebaseAuth.instance.signInAnonymously(); }}…The feed must show the three newest comments under every post. How does that requirement change your Firestore model?
A message you just sent shows up in the list instantly, then jumps to a different position a second later. What are the snapshots telling you?
In airplane mode your
await docRef.set(...)never returns, yet the new row is already on screen. Is that a bug?// wrong: offline this Future never completes and the spinner never stopsFuture<void> badSave(String text) async { setState(() => _saving = true); await db.collection('notes').add({'text': text}); setState(() => _saving = false);}…Two users tap Buy on the last item at the same moment and both get an order. What is wrong with this code?
Future<void> buy(String itemId, String uid) async { final item = db.doc('items/$itemId'); final snap = await item.get(); final stock = snap.get('stock') as int; if (stock <= 0) throw const SoldOut(); await item.update({'stock': stock - 1}); await db.collection('orders').add({'itemId': itemId, 'uid': uid});}This query works against the emulator, but in production the stream fails with
failed-precondition. Why, and how do you fix it for good?Stream<List<Order>> openOrders(String uid) => db .collection('orders') .where('userId', isEqualTo: uid) .where('status', isEqualTo: 'open') .orderBy('createdAt', descending: true) .limit(20) .snapshots() .map((s) => s.docs.map(Order.fromDoc).toList());How do Firestore security rules work, and why can't hiding the Delete button from non-authors replace them?
rules_version = '2';service cloud.firestore { match /databases/{database}/documents { match /notes/{noteId} { allow read, delete: if request.auth != null && resource.data.ownerId == request.auth.uid;…Push notifications show up when the app is closed, but nothing appears while the user has it open. How does
firebase_messaginghandle each app state?@pragma('vm:entry-point') // release builds tree-shake it otherwiseFuture<void> _onBackground(RemoteMessage message) async { // A separate isolate: no providers, no navigator, no app state. await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);}…Find the bug: after some navigation, one foreground push shows the same banner two or three times.
class _InboxScreenState extends State<InboxScreen> { int _unread = 0; @override void initState() { super.initState(); FirebaseMessaging.onMessage.listen((message) { showLocalBanner(message.notification?.title); setState(() => _unread++); }); } @override Widget build(BuildContext context) => Text('Unread: $_unread');}Crashlytics is in the app, users report crashes every day, and the dashboard is empty. What is missing from the wiring?
Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); final crashlytics = FirebaseCrashlytics.instance; await crashlytics.setCrashlyticsCollectionEnabled(!kDebugMode);…What do you log with Firebase Analytics in a Flutter app, and what must never go into it?
The splash screen hangs for eight seconds on a weak connection because startup awaits Remote Config. How should that be wired instead?
final rc = FirebaseRemoteConfig.instance; Future<void> bootstrapConfig() async { await rc.setConfigSettings(RemoteConfigSettings( fetchTimeout: const Duration(seconds: 8), // default 60 s minimumFetchInterval:…Your callable Cloud Function works against the emulator but returns
internalwith no message in production. What is going on?The Firestore bill jumped to five figures in a month while the user count stayed flat. Where do you look in the Flutter code first?
// wrong: a new stream on every rebuild re-attaches the listener@overrideWidget build(BuildContext context) => StreamBuilder<QuerySnapshot>( stream: db.collection('orders').where('userId', isEqualTo: uid).snapshots(), builder: _rows, );…Find the bug in this
OrdersRepository:watchMyOrders()is meant to follow whoever is signed in right now.class OrdersRepository { OrdersRepository(this._auth, this._db); final FirebaseAuth _auth; final FirebaseFirestore _db; // Orders of whoever is signed in right now. Stream<List<Order>> watchMyOrders() => _auth.authStateChanges().asyncExpand((user) { if (user == null) return Stream.value(const <Order>[]); return _db .collection('orders') .where('userId', isEqualTo: user.uid) .snapshots() .map((s) => s.docs.map(Order.fromDoc).toList()); });}Anyone can pull the API key out of your APK and call Firestore directly. What does App Check add, and what does it still not protect?
Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // Before the first Firestore, Storage or Functions call. await FirebaseAppCheck.instance.activate(…How do you test a Firebase-backed Flutter app so that no test run touches production and no widget test needs a network?
// 1. Widget tests: the seam is a repository, Firebase never loads.class FakeOrders implements OrderRepository { FakeOrders(this.orders); final List<Order> orders; @override Stream<List<Order>> watch(String uid) => Stream.value(orders);…A client asks whether to build on Firebase, on Supabase, or on your own backend. How do you decide, and how do you keep the door open?