Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Add Push Notifications to Your FlutterFlow Project

FlutterFlow has built-in Firebase Cloud Messaging support. Enable it in Settings > Push Notifications, upload your Apple APNs authentication key for iOS, add the Request Notification Permission action to your onboarding flow, store the FCM token in the user's Firestore document, then test by sending from the Firebase Console. iOS notifications silently fail if you skip the APNs key upload.

What you'll learn

  • How to enable push notifications in FlutterFlow Settings
  • How to upload an APNs key for iOS notification delivery
  • How to request permission and store FCM tokens in Firestore
  • How to send a test notification from the Firebase Console
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner9 min read25-35 minFlutterFlow Free+ (Firebase required)March 2026RapidDev Engineering Team
TL;DR

FlutterFlow has built-in Firebase Cloud Messaging support. Enable it in Settings > Push Notifications, upload your Apple APNs authentication key for iOS, add the Request Notification Permission action to your onboarding flow, store the FCM token in the user's Firestore document, then test by sending from the Firebase Console. iOS notifications silently fail if you skip the APNs key upload.

Push Notifications from Zero to Working

Push notifications are one of the highest-ROI features in any mobile app — but the setup involves multiple platforms, keys, and configuration steps that beginners often get partially right. This guide walks through the exact sequence: enabling FCM in FlutterFlow, configuring the Apple Push Notification service for iOS, wiring up the permission flow in your app, and verifying everything works end-to-end before you write a single line of custom code.

Prerequisites

  • FlutterFlow project with Firebase connected (Settings > Firebase > Connect)
  • Apple Developer account ($99/yr) if targeting iOS
  • Firebase project with iOS and Android apps registered
  • Basic familiarity with Firestore collections and documents

Step-by-step guide

1

Enable Push Notifications in FlutterFlow Settings

Open your FlutterFlow project and navigate to Settings (gear icon in the left panel) > Notifications. Toggle 'Enable Push Notifications' to on. FlutterFlow will automatically add the firebase_messaging package to your project and generate the required AndroidManifest.xml changes for Android. For iOS, you also need to add the Push Notifications capability — FlutterFlow handles this in the generated Xcode project. Once enabled, a confirmation banner appears and the toggle stays green. This step takes about 30 seconds and has no cost on any FlutterFlow plan.

Expected result: The Push Notifications toggle is green and FlutterFlow shows 'Push Notifications Enabled' status.

2

Create and Upload Your APNs Authentication Key for iOS

iOS notifications require an Apple Push Notification service key uploaded to Firebase. In Apple Developer Portal, go to Certificates, Identifiers & Profiles > Keys > click the + button. Name the key, check 'Apple Push Notifications service (APNs)', and click Continue then Register. Download the .p8 key file — you can only download it once. Note your Key ID and Team ID (visible in Membership section). In Firebase Console, go to Project Settings > Cloud Messaging > Apple app configuration and upload the .p8 file along with the Key ID and Team ID. Back in FlutterFlow Settings > Notifications, confirm the APNs status shows as configured.

Expected result: Firebase Console shows a green checkmark next to your iOS app in the Cloud Messaging settings page.

3

Add Request Permission Action to Your Onboarding Flow

Users must grant notification permission before your app can deliver any notifications. Find the page in your app where it makes the most sense to ask — typically the end of onboarding or when a feature that requires notifications is first used. Select a Button widget, open its On Tap action flow, and click Add Action. Search for 'Request Notification' and select 'Request Notification Permission' from the FlutterFlow Actions list. Add a conditional branch after it: if permission is Granted, proceed normally; if Denied, show an informational alert explaining why notifications matter and offering to open Settings. Avoid asking for notification permission on first app launch before the user understands your app's value.

Expected result: Running the app shows the native iOS or Android permission dialog. Granting permission returns 'Granted' in the action output.

4

Store the FCM Token in the User's Firestore Document

The FCM token is the device address you need to send targeted notifications. After the user grants permission, retrieve and store this token so your backend can find it later. In the same action flow, after the permission grant branch, add a Custom Action (or use the Get FCM Token action if visible in your FlutterFlow version). Then add an Update Document action targeting the current user's document in your 'users' Firestore collection. Set the field 'fcm_token' to the output of the Get FCM Token action. Also store 'fcm_token_updated_at' as the current timestamp so you can detect stale tokens. Do this on every app launch — tokens can rotate and you always want the freshest one.

save_fcm_token.dart
1import 'package:firebase_messaging/firebase_messaging.dart';
2import 'package:cloud_firestore/cloud_firestore.dart';
3import 'package:firebase_auth/firebase_auth.dart';
4
5Future<void> saveFcmToken() async {
6 final String? token = await FirebaseMessaging.instance.getToken();
7 final String? userId = FirebaseAuth.instance.currentUser?.uid;
8
9 if (token == null || userId == null) return;
10
11 await FirebaseFirestore.instance
12 .collection('users')
13 .doc(userId)
14 .update({
15 'fcm_token': token,
16 'fcm_token_updated_at': FieldValue.serverTimestamp(),
17 'platform': Theme.of(navigatorKey.currentContext!).platform.name,
18 });
19
20 // Listen for token refresh
21 FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
22 FirebaseFirestore.instance
23 .collection('users')
24 .doc(userId)
25 .update({'fcm_token': newToken});
26 });
27}

Expected result: The logged-in user's Firestore document now has an fcm_token field containing a long alphanumeric string starting with the device identifier.

5

Send a Test Notification from Firebase Console

Before writing any backend code, confirm the entire chain works using the Firebase Console. Go to Firebase Console > Engage > Messaging > Send your first message. Enter a notification title and body text. Click 'Send test message' (not the full campaign flow). Paste the FCM token you saved in the previous step into the test dialog and click Test. The notification should appear on the device within 5-10 seconds. On iOS, make sure your device has granted notification permission and that your APNs key was uploaded correctly. On Android, make sure the app is not in the foreground (background or closed for the system tray notification to show).

Expected result: The notification appears in the device's notification shade with the exact title and body you typed in the Firebase Console.

Complete working example

push_notification_init.dart
1import 'package:firebase_messaging/firebase_messaging.dart';
2import 'package:cloud_firestore/cloud_firestore.dart';
3import 'package:firebase_auth/firebase_auth.dart';
4
5// ─── Background Message Handler (top-level function) ────────────────────────
6// Must be a top-level function, not a class method
7@pragma('vm:entry-point')
8Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
9 // Handle background messages here
10 // Do not access BuildContext from here
11 print('Background message received: ${message.messageId}');
12}
13
14// ─── Main Initialization ─────────────────────────────────────────────────────
15
16Future<void> initPushNotifications() async {
17 // Register background handler before calling Firebase.initializeApp
18 FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
19
20 // Request permission (iOS — Android 13+ also needs this)
21 final NotificationSettings settings =
22 await FirebaseMessaging.instance.requestPermission(
23 alert: true,
24 announcement: false,
25 badge: true,
26 carPlay: false,
27 criticalAlert: false,
28 provisional: false,
29 sound: true,
30 );
31
32 if (settings.authorizationStatus == AuthorizationStatus.authorized) {
33 await saveFcmToken();
34 }
35
36 // Handle notification taps when app was terminated
37 final RemoteMessage? initialMessage =
38 await FirebaseMessaging.instance.getInitialMessage();
39 if (initialMessage != null) {
40 _routeFromNotification(initialMessage.data);
41 }
42
43 // Handle notification taps when app was in background
44 FirebaseMessaging.onMessageOpenedApp.listen(_routeFromNotification);
45}
46
47// ─── Token Storage ────────────────────────────────────────────────────────────
48
49Future<void> saveFcmToken() async {
50 final String? token = await FirebaseMessaging.instance.getToken();
51 final String? userId = FirebaseAuth.instance.currentUser?.uid;
52 if (token == null || userId == null) return;
53
54 await FirebaseFirestore.instance.collection('users').doc(userId).update({
55 'fcm_token': token,
56 'fcm_token_updated_at': FieldValue.serverTimestamp(),
57 });
58
59 FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
60 FirebaseFirestore.instance
61 .collection('users')
62 .doc(userId)
63 .update({'fcm_token': newToken});
64 });
65}
66
67// ─── Navigation Routing ───────────────────────────────────────────────────────
68
69void _routeFromNotification(Map<String, dynamic> data) {
70 final String page = data['target_page'] ?? '';
71 if (page.isNotEmpty) {
72 // Set FFAppState navigation target
73 FFAppState().pendingNavPage = page;
74 FFAppState().pendingNavId = data['id'] ?? '';
75 }
76}

Common mistakes when adding Push Notifications to Your FlutterFlow Project

Why it's a problem: Forgetting to upload the APNs key for iOS — notifications silently fail

How to avoid: Upload the .p8 APNs key to Firebase Console > Project Settings > Cloud Messaging > Apple app configuration. Verify the Key ID and Team ID match exactly what is shown in your Apple Developer account.

Why it's a problem: Saving the FCM token only once at sign-up instead of on every app launch

How to avoid: Call saveFcmToken() every time the user opens the app when authenticated, and listen to FirebaseMessaging.instance.onTokenRefresh to update Firestore whenever the token changes.

Why it's a problem: Requesting notification permission on the very first screen of the app

How to avoid: Ask for permission at a meaningful moment — after the user completes onboarding, enables a feature that needs alerts, or explicitly taps a 'Turn on notifications' button.

Best practices

  • Always register the background message handler as a top-level function (not a class method) — FCM isolates background handling and class methods will throw errors.
  • Store platform alongside the FCM token so your Cloud Function can send platform-specific APNS/Android configs in one payload.
  • Use batch writes when sending notifications to multiple users — Cloud Functions can fan out to 500 tokens per batch operation efficiently.
  • Add a 'notifications_enabled' boolean to the user document so users can opt out from inside your app without going to device settings.
  • Test on a physical iOS device — the simulator cannot receive actual push notifications.
  • Include a notification_id in your data payload so you can deduplicate and track delivery on the server side.
  • Monitor FCM delivery rates in Firebase Console > Cloud Messaging > Reports to catch delivery issues before users complain.

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I am building a FlutterFlow app with Firebase. Show me step-by-step how to set up Firebase Cloud Messaging for both iOS and Android, request notification permission from the user at the right time, save and refresh the FCM token in Firestore, and handle notification taps when the app is closed versus backgrounded versus open.

FlutterFlow Prompt

In my FlutterFlow app, add an action flow on the main dashboard page that: 1) calls a Custom Action to get the FCM token, 2) updates the current user's Firestore document fcm_token field, 3) listens for token refresh events. Also add a Request Notification Permission action to the end of my onboarding wizard's last page.

Frequently asked questions

Why are push notifications working on Android but not iOS?

The most common cause is a missing or incorrectly uploaded APNs authentication key. Go to Firebase Console > Project Settings > Cloud Messaging and verify your iOS app shows a green checkmark with your APNs key. Also confirm the App ID in your Apple Developer account has the Push Notifications capability enabled.

Can I send push notifications on the FlutterFlow free plan?

Yes. Push notifications via Firebase Cloud Messaging are free on all FlutterFlow plans. FCM itself is free through Firebase. You only pay Firebase for Firestore reads/writes used to look up FCM tokens, which falls within the free Spark plan limits for small apps.

How do I send notifications to all users at once?

Query all user documents from Firestore where fcm_token is not empty, then use the Firebase Admin SDK in a Cloud Function to send in batches of 500 using sendEachForMulticast(). Avoid sending individual messages in a loop — it is slow and hits rate limits.

Why does my app show a notification when in the background but not when open?

FCM suppresses system tray notifications when the app is in the foreground. You must listen to the FirebaseMessaging.onMessage stream and show your own in-app UI — a banner widget, a badge update, or a snackbar — to notify the user when the app is active.

Do I need to handle notification permissions differently for Android 13+?

Yes. Android 13 introduced a runtime notification permission similar to iOS. Call FirebaseMessaging.instance.requestPermission() for both platforms — FlutterFlow's built-in Request Notification Permission action handles this automatically on both OS versions.

What happens if a user denies notification permission on iOS?

Once denied, the OS permission dialog will never appear again for your app. You must direct the user to Settings > Your App > Notifications to re-enable. Show a friendly in-app prompt explaining the value of notifications before triggering the permission request to maximize grant rates.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.