Blog
ENGINEERINGNOTIFICATIONS LANDSCAPE

Flutter Notifications: Add In-App Inbox and Push in 10 Lines of Code

Kyle Seyler

January 07, 2026

flutter plus courier

Table of contents

TL;DR

The Code

Making It Match Your App

Why Not Just Firebase?

Flutter's Production Era

What You're Actually Building When You Build Notifications

What the SDK Actually Does

Preferences and Compliance

Getting Started πŸš€

Flutter developers ship fast. That's the whole point. Single codebase, consistent UI across iOS and Android, hot reload that actually works. You picked Flutter because you wanted to stop rewriting the same screens twice.

So why are you still hand-rolling notification infrastructure?

Building an in-app inbox from scratch takes weeks. Maintaining it takes forever. Or you can add one in 10 lines of code and get back to building what actually differentiates your app.

TL;DR

Add courier_flutter to your project, call Courier.shared.signIn() at login, drop in the CourierInbox widget. You get a real-time notification inbox, push support for iOS and Android, user preference controls, and cross-channel state sync (open an email, the inbox message marks as read). Works with FCM and APNs out of the box. Handles token management, digest batching, GDPR compliance, and all the edge cases that make building notifications yourself take a quarter instead of a week. Same infrastructure Twilio uses for 10+ million developers.

The Code

Install the package:

Copied!

flutter pub add courier_flutter

Sign in your user (typically at login):

Copied!

import 'package:courier_flutter/courier_flutter.dart';
_signIn() async {
await Courier.shared.signIn(
accessToken: 'your_users_jwt', // Generate this on your backend
userId: 'your_user_id',
);
}

Add the inbox widget:

Copied!

import 'package:courier_flutter/ui/inbox/courier_inbox.dart';
@override
Widget build(BuildContext context) {
return CourierInbox(
onMessageClick: (message, index) {
message.isRead ? message.markAsUnread() : message.markAsRead();
},
);
}

Add user preferences if you want them:

Copied!

import 'package:courier_flutter/ui/preferences/courier_preferences.dart';
@override
Widget build(BuildContext context) {
return CourierPreferences(
mode: TopicMode(),
);
}

That's the whole integration. The SDK handles real-time sync, read/unread state, push token management for both FCM and APNs, and WebSocket reconnection when your app moves between foreground and background.

Making It Match Your App

The inbox widget ships with theming that adapts to your app's Material or Cupertino design system automatically. If you're using Material3 or custom themes, the inbox picks up those defaults without configuration. But when you need deeper customization, everything's exposed through the theme parameter.

product notifications

Copied!

CourierInbox(
theme: CourierInboxTheme(
brandColor: Color(0xFF6C5CE7),
unreadIndicatorStyle: CourierInboxUnreadIndicatorStyle.dot,
titleStyle: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
bodyStyle: TextStyle(fontSize: 14, color: Colors.grey[700]),
),
onMessageClick: (message, index) {
message.isRead ? message.markAsUnread() : message.markAsRead();
},
)

You can override:

  • 🎨 Brand colors for unread indicators and CTAs
  • ✏️ Typography for titles and timestamps
  • πŸ”΅ Unread indicator styles (dot, line, or badge)
  • ⏳ Loading states and empty state UI
  • πŸ‘† Swipe actions and long-press behavior

The widget uses Flutter's standard theming system throughout, so customization follows patterns you already know.

Why Not Just Firebase?

If you're building on Flutter, you're probably already using Firebase Cloud Messaging for push. So why add another SDK?

FCM handles delivery. It gets a notification from your server to the device. But that's where it stops. You still need to build the inbox UI where users see past notifications, read/unread state that persists across app launches, a preferences screen where users control what they receive, cross-channel orchestration for email and SMS and push and in-app messages, and read state sync so when a user opens an email, the related inbox message marks as read.

That last one is harder than it sounds. When someone opens a marketing email at their desk, your app needs to know that message is read before they even unlock their phone. Courier syncs read state across channels automatically. Open an email, the inbox message gets marked as read. Tap an inbox message, the associated push notification clears. This cross-channel state management is what takes teams weeks to build correctly, and it's running in production the moment you integrate the SDK.

FCM and Courier aren't competing. FCM is your delivery pipe. Courier is the orchestration layer sitting on top, handling inbox UI, preferences, routing logic, and the state management that ties everything together. Most teams use both. Courier registers your FCM tokens automatically and handles token refresh when users reinstall your app or revoke notification permissions.

Flutter's Production Era

Flutter 3.38 dropped in November 2025, and Google officially declared this the "Production Era." The experimental phases are over. Impeller is stable. The framework handles 16KB page sizes for Android 15 compliance out of the box. The 3.38 release fully supports iOS 26, Xcode 26, and macOS 26, all released in September. Flutter now supports Apple's mandated UIScene lifecycle, which means proper multi-window support on iPadOS through Stage Manager, improved state restoration, and correct background/foreground transitions. If you're shipping to iOS, your Flutter apps are ready for the latest Apple requirements without extra work.

flutter and courier

Flutter 4.0 is expected in early 2026, bringing the Impeller 2.0 rendering engine and deeper AI/ML integration. Google is already using Flutter to build the interactive UI components in Gemini and NotebookLM. When Google needs a fast, cross-platform way to render AI-generated interfaces, they reach for Flutter. According to Apptopia, Flutter now accounts for nearly 30% of all new free iOS apps. JetBrains developer surveys show it's been the most-used cross-platform framework since 2021.

The framework's maturity means teams are building production apps faster than ever. But speed-to-market only matters if you're not wasting cycles on solved problems.

What You're Actually Building When You Build Notifications

Here's what teams underestimate when they start building notification infrastructure in-house:

  • πŸ“± FCM setup for Android and APNs certificates/entitlements for iOS
  • πŸ”‘ Token management that survives installs, updates, and permission changes
  • ⚑ Foreground, background, and terminated state handlers (each behaves differently)
  • πŸ”Œ WebSocket or polling for real-time inbox sync
  • βœ… Read/unread state that persists correctly across app restarts
  • πŸ“„ Pagination, empty states, pull-to-refresh that doesn't feel janky
  • βš™οΈ Preferences UI that syncs with your backend sending logic

That's not a sprint. That's a quarter. And then someone has to maintain it while your app evolves.

When Twilio needed to unify notifications for their own platform serving 10+ million developers, they chose Courier. As their Technical Lead put it: "We chose Courier because the depth of the inbox and multi-channel integrations allowed us to choose one notification platform for all products and teams at Twilio."

What the SDK Actually Does

πŸ“¬ Inbox:
Real-time updates via WebSocket, read/unread state management, long press gestures with haptic feedback, pull-to-refresh with proper empty states, brand color integration for unread indicators, pagination, and cross-channel state sync so marking a message as read in email updates it in-app immediately.

βš™οΈ Preferences:
Topic-based and channel-based modes, syncs to Courier's backend automatically, and themes to match your app. When a user toggles a preference, it propagates instantly and your send logic respects it without extra code on your end.

πŸ”” Push:
Automatic token management for both FCM and APNs, foreground/background/terminated state handlers, and token refresh logic when users reinstall or revoke permissions. You don't write any of this.

πŸ“Š Digests:
Schedule notifications on daily, weekly, or custom intervals. Batch multiple events into single notifications, configure per-user (some want real-time, others want daily summaries), and works across all channels so you can combine 20 activity events into one email or push. The digest logic runs on Courier's backend, which means you don't need to track pending notifications or build batch-send infrastructure.

The SDK supports iOS 13+ and Android API 21+. Beyond the Flutter SDK, Courier connects to 50+ providers including SendGrid, Twilio SMS, Slack, and Teams. If you're building a SaaS product, the same notification infrastructure handles onboarding flows, payment reminders, and multi-channel orchestration.

Preferences and Compliance

GDPR and CCPA don't just require user consent. They require giving users ongoing control over what messages they receive. Building a preference center that actually works means:

  • πŸŽ›οΈ UI for toggling notification categories and channels
  • πŸ”’ Backend logic to respect those preferences when sending
  • πŸ”„ Keeping frontend and backend in sync
  • πŸ“‹ Audit logs proving you honored user choices

Courier's preference widget handles the UI. When a user toggles a preference, it syncs to Courier's backend immediately. Your send logic automatically respects those preferences without extra checks on your end. You send a "product_updates" notification, Courier checks if that user opted in, and only delivers if they did. The preference data lives in Courier's user profiles, which means it persists across devices and works the same whether you're sending push, email, or SMS.

This isn't just compliance theater. When users feel in control, they leave notifications enabled instead of revoking permissions at the OS level. That's worth the integration cost alone.

Getting Started πŸš€

Copied!

flutter pub add courier_flutter

Generate a JWT on your backend for user authentication, call Courier.shared.signIn() when your user logs in, and add CourierInbox and CourierPreferences widgets where they fit your UX.

Full documentation: github.com/trycourier/courier-flutter

Similar resources

courier and expo push notifications
GuideEngineering

Expo Push Notifications: The Complete Implementation Guide (SDK 52+)

Expo push notifications are alerts sent from a server to a user's phone, even when the app isn't open. To set them up, install the expo-notifications library, ask the user for permission, and get a unique push token for their device. Your server sends a message to Expo's push service with that token, and Expo delivers it through Apple or Google. Push notifications only work on real phones, not simulators. Local notifications are different β€” they're scheduled by the app itself for things like reminders. You can also route Expo push through services like Courier to add email, SMS, and Slack fallbacks.

By Kyle Seyler

February 24, 2026

email infrastructure providers
AIGuideEngineering

Best Email API Providers for Developers in 2026: SendGrid vs Postmark vs Mailgun vs SES vs Resend

Your email provider sticks with you longer than most technical decisions. Courier handles notification infrastructure for thousands of teams, so we went deep on the six email providers that show up most: SendGrid, Postmark, Mailgun, Amazon SES, Resend, and SMTP. This guide covers real API primitives, actual code from each provider's docs, Courier integration examples with provider overrides, and an honest read on where each developer experience holds up and where it breaks down. We also asked Claude to review every API and tell us which one it would wire up first. The answer surprised us.

By Kyle Seyler

February 23, 2026

Courier MCP is open source
AIEngineering

The Courier MCP Server Is Open Source. Here's How It Actually Works.

Courier's MCP server is open source at github.com/trycourier/courier-mcp. It connects AI coding tools like Cursor and Claude Code to your Courier account so they can send messages, manage users, and install SDKs without hallucinating API details. This post walks through the actual codebase: how 16 tool classes are registered (and how a config allowlist gates most of them), why we pull installation guides from GitHub at runtime instead of bundling them, how the DocsTools class generates live JWTs alongside setup instructions, and what the SdkContextTools class does in the repo to prevent v7/v8 SDK conflicts (even though it isn't wired into the server yet).

By Mike Miller

February 06, 2026

Multichannel Notifications Platform for SaaS

Products

Platform

Integrations

Customers

Blog

API Status

Subprocessors


Β© 2026 Courier. All rights reserved.