<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Codexlancers</title>
    <description>The latest articles on DEV Community by Codexlancers (@codexlancers).</description>
    <link>https://dev.to/codexlancers</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3857287%2Fa8e4508f-a0b0-447b-a06a-9bc5efa2ebf5.jpeg</url>
      <title>DEV Community: Codexlancers</title>
      <link>https://dev.to/codexlancers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codexlancers"/>
    <language>en</language>
    <item>
      <title>🔔 Flutter Push Notifications (Foreground, Background, Terminated) — Complete Fix Guide</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Tue, 02 Jun 2026 06:07:09 +0000</pubDate>
      <link>https://dev.to/codexlancers/flutter-push-notifications-foreground-background-terminated-complete-fix-guide-4emb</link>
      <guid>https://dev.to/codexlancers/flutter-push-notifications-foreground-background-terminated-complete-fix-guide-4emb</guid>
      <description>&lt;p&gt;Push notifications in Flutter look easy…&lt;br&gt;
until you actually try to implement them.&lt;/p&gt;

&lt;p&gt;Everything seems fine - until:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notifications don't show in foreground&lt;/li&gt;
&lt;li&gt;Background handlers never trigger&lt;/li&gt;
&lt;li&gt;And terminated state? Completely broken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've been there… yeah, same&lt;/p&gt;

&lt;p&gt;We've faced all of this while working on a production app, and this guide is the &lt;strong&gt;exact setup&lt;/strong&gt; that finally worked.&lt;/p&gt;

&lt;p&gt;First - Understand Notification States (This is where most people go wrong)&lt;br&gt;
Before writing a single line of code, you need to understand this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbnnluc4lrw5nu2r4ojgq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbnnluc4lrw5nu2r4ojgq.png" alt="Types of notifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 Each state behaves &lt;strong&gt;differently&lt;/strong&gt;. And if you treat them the same, things will break.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic Setup
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Add dependencies
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;// pubspec.yaml&lt;/span&gt;

&lt;span class="na"&gt;firebase_core&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^4.6.0&lt;/span&gt;
&lt;span class="na"&gt;firebase_messaging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^16.1.3&lt;/span&gt;
&lt;span class="na"&gt;flutter_local_notifications&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^21.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Initialize Firebase
&lt;/h3&gt;

&lt;p&gt;Before using FCM, initialize Firebase when your app starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Firebase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Request Notification Permission
&lt;/h3&gt;

&lt;p&gt;This step is mandatory on iOS and Android 13+.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt; &lt;span class="n"&gt;messaging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;messaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requestPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;alert:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;badge:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;sound:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why is this important?
&lt;/h3&gt;

&lt;p&gt;Starting from Android 13, Android requires explicit notification permission, similar to iOS.&lt;/p&gt;

&lt;p&gt;If permission is not granted, notifications won't appear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Android Notification Channel (Must for Android)
&lt;/h2&gt;

&lt;p&gt;Without this, notifications may not show or may appear silently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AndroidNotificationChannel&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AndroidNotificationChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'high_importance_channel'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'High Importance Notifications'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;description:&lt;/span&gt; &lt;span class="s"&gt;'This channel is used for important notifications.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;importance:&lt;/span&gt; &lt;span class="n"&gt;Importance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;high&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;FlutterLocalNotificationsPlugin&lt;/span&gt; &lt;span class="n"&gt;flutterLocalNotificationsPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;FlutterLocalNotificationsPlugin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;flutterLocalNotificationsPlugin&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;resolvePlatformSpecificImplementation&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;
        &lt;span class="n"&gt;AndroidFlutterLocalNotificationsPlugin&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;createNotificationChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  iOS Foreground Notification Setup
&lt;/h2&gt;

&lt;p&gt;iOS requires this to properly show notifications in foreground:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setForegroundNotificationPresentationOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;alert:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;badge:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;sound:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Without this, notifications may not appear even if everything else is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foreground Notifications (Most Common Confusion)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;You send a notification and nothing shows when the app is open. &lt;br&gt;
Feels like it's broken, right?&lt;/p&gt;
&lt;h3&gt;
  
  
  The reality
&lt;/h3&gt;

&lt;p&gt;FCM does NOT display notifications in foreground.&lt;/p&gt;
&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;You must show it manually using local notifications:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;RemoteMessage&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;showLocalNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 This is where most developers get stuck initially.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background Notifications
&lt;/h2&gt;

&lt;p&gt;This is where things start working automatically, but only if you do it right.&lt;/p&gt;

&lt;h3&gt;
  
  
  Works automatically IF your payload includes:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"notification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"World"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⚠️ Using data-only payload?
&lt;/h2&gt;

&lt;p&gt;Then you MUST handle it manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onBackgroundMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_firebaseMessagingBackgroundHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_firebaseMessagingBackgroundHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RemoteMessage&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Firebase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Required in background isolate&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Handling background message"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Also, this function must be top-level.&lt;br&gt;
(Not inside a class - easy mistake.)&lt;/p&gt;
&lt;h2&gt;
  
  
  Terminated State (Most Confusing Part)
&lt;/h2&gt;

&lt;p&gt;This is where most implementations fail.&lt;/p&gt;
&lt;h3&gt;
  
  
  The issue
&lt;/h3&gt;

&lt;p&gt;User taps notification → app opens → but nothing happens.&lt;/p&gt;
&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;Handle the initial message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;RemoteMessage&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;initialMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInitialMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initialMessage&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;handleNotificationClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initialMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also listen when app is opened from background:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onMessageOpenedApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;handleNotificationClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Without this, deep linking or navigation won't work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigation Tip
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;handleNotificationClick()&lt;/strong&gt; should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read payload data&lt;/li&gt;
&lt;li&gt;Navigate to a specific screen&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Local Notification Setup (Required for Foreground)
&lt;/h2&gt;

&lt;p&gt;Without this, your foreground notifications will never show.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FlutterLocalNotificationsPlugin&lt;/span&gt; &lt;span class="n"&gt;flutterLocalNotificationsPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;FlutterLocalNotificationsPlugin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;showLocalNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RemoteMessage&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;androidDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AndroidNotificationDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'channel_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'channel_name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;importance:&lt;/span&gt; &lt;span class="n"&gt;Importance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;priority:&lt;/span&gt; &lt;span class="n"&gt;Priority&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;high&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="n"&gt;generalNotificationDetails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="n"&gt;NotificationDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;android:&lt;/span&gt; &lt;span class="n"&gt;androidDetails&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;flutterLocalNotificationsPlugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;generalNotificationDetails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Mistakes (From Real Experience)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Not asking notification permission (Android 13+ especially)&lt;/li&gt;
&lt;li&gt;Expecting foreground notifications to show automatically&lt;/li&gt;
&lt;li&gt;Using only data payload and expecting UI&lt;/li&gt;
&lt;li&gt;Background handler inside a class (won't work)&lt;/li&gt;
&lt;li&gt;Forgetting getInitialMessage()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 We've personally hit &lt;strong&gt;almost all of these&lt;/strong&gt; 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Push notifications in Flutter are &lt;strong&gt;not plug-and-play&lt;/strong&gt;.&lt;br&gt;
They require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proper setup&lt;/li&gt;
&lt;li&gt;Understanding of app states&lt;/li&gt;
&lt;li&gt;Correct payload structure&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;If your notifications are not working, 90% of the time:&lt;br&gt;
👉 You didn't handle foreground manually&lt;br&gt;
👉 OR your payload is wrong&lt;/p&gt;

&lt;p&gt;If your notifications are not working on iOS or APNs token is not generating, check this:&lt;br&gt;
👉 Flutter APNs Token Not Generating (Complete Fix Guide)&lt;/p&gt;

&lt;p&gt;If this saved you hours of debugging, consider following for more Flutter deep dives.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>firebase</category>
    </item>
    <item>
      <title>HeyGen vs Tavus vs Anam</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Mon, 25 May 2026 11:12:25 +0000</pubDate>
      <link>https://dev.to/codexlancers/heygen-vs-tavus-vs-anam-2m96</link>
      <guid>https://dev.to/codexlancers/heygen-vs-tavus-vs-anam-2m96</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fge80enzklazr34nxygaq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fge80enzklazr34nxygaq.png" alt=" " width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Real Difference Nobody Explains Properly&lt;/strong&gt;&lt;br&gt;
The AI avatar industry is exploding right now.&lt;/p&gt;

&lt;p&gt;Every week, a new “AI human” platform appears online claiming:&lt;/p&gt;

&lt;p&gt;➪ realistic avatars&lt;br&gt;
➪ live conversations&lt;br&gt;
➪ AI agents&lt;br&gt;
➪ emotional interaction&lt;br&gt;
➪ digital humans&lt;/p&gt;

&lt;p&gt;But here’s the problem:&lt;/p&gt;

&lt;p&gt;Most people compare platforms like:&lt;/p&gt;

&lt;p&gt;➪ &lt;a href="https://www.heygen.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;HeyGen&lt;/a&gt;&lt;br&gt;
➪ &lt;a href="https://www.tavus.io/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Tavus&lt;/a&gt;&lt;br&gt;
➪ &lt;a href="https://anam.ai/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Anam&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;as if they are the same type of product.&lt;/p&gt;

&lt;p&gt;They are NOT.&lt;/p&gt;

&lt;p&gt;And this confusion causes many startups and mobile app builders to choose the wrong platform.&lt;/p&gt;

&lt;p&gt;Because in reality:&lt;/p&gt;

&lt;p&gt;➪ HeyGen is mainly an AI video generation platform&lt;br&gt;
➪ Tavus is a full conversational AI avatar platform&lt;br&gt;
➪ Anam is primarily an avatar rendering platform&lt;/p&gt;

&lt;p&gt;That distinction changes everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Simplest Explanation&lt;/strong&gt;&lt;br&gt;
HeyGen → Creates AI videos&lt;br&gt;
Tavus → Provides full AI conversation system with avatar&lt;br&gt;
Anam → Provides realistic avatar rendering only&lt;/p&gt;

&lt;p&gt;This is the most important thing to understand before integrating any of them into a mobile app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. HeyGen — Best for AI Video Generation&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.heygen.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;HeyGen Official Website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfiwrqtsumw79o6ptefi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfiwrqtsumw79o6ptefi.png" alt=" " width="720" height="349"&gt;&lt;/a&gt;&lt;br&gt;
HeyGen became popular because it made AI avatars easy for everyone.&lt;/p&gt;

&lt;p&gt;You simply:&lt;/p&gt;

&lt;p&gt;➪ Type a script&lt;br&gt;
➪ Choose an avatar&lt;br&gt;
➪ Generate a video&lt;/p&gt;

&lt;p&gt;And within minutes, you get a professional-looking AI spokesperson.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What HeyGen Is Actually Good At&lt;/strong&gt;&lt;br&gt;
HeyGen is excellent for:&lt;/p&gt;

&lt;p&gt;➪ marketing videos&lt;br&gt;
➪ training videos&lt;br&gt;
➪ YouTube content&lt;br&gt;
➪ onboarding videos&lt;br&gt;
➪ multilingual content&lt;br&gt;
➪ AI presentations&lt;/p&gt;

&lt;p&gt;And honestly, for content creation, it’s one of the easiest platforms available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvq37jqaikaobhwovi0s2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvq37jqaikaobhwovi0s2.png" alt=" " width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Tavus — A Complete Conversational AI Human Platform&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.tavus.io/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Tavus Official Website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qp676o1wpyinw8gzbr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qp676o1wpyinw8gzbr2.png" alt=" " width="720" height="401"&gt;&lt;/a&gt;&lt;br&gt;
This is where things become very different.Tavus is NOT just an avatar platform.&lt;/p&gt;

&lt;p&gt;It’s a:&lt;br&gt;
full conversational AI human system.&lt;/p&gt;

&lt;p&gt;That means Tavus handles much more than just showing a face on screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Tavus Actually Provides&lt;/strong&gt;&lt;br&gt;
Tavus provides:&lt;/p&gt;

&lt;p&gt;➪ live face-to-face AI conversations&lt;br&gt;
➪ real-time interaction&lt;br&gt;
➪ conversational flow&lt;br&gt;
➪ interruption handling&lt;br&gt;
➪ session management&lt;br&gt;
➪ memory systems&lt;br&gt;
➪ AI orchestration&lt;br&gt;
➪ conversational behaviors&lt;br&gt;
➪ streaming infrastructure&lt;/p&gt;

&lt;p&gt;This is a huge difference compared to simple avatar platforms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tavus Feels Like Talking to an AI Person&lt;/strong&gt;&lt;br&gt;
With Tavus:&lt;/p&gt;

&lt;p&gt;➪ users can speak naturally&lt;br&gt;
➪ the AI responds live&lt;br&gt;
➪ conversations feel dynamic&lt;br&gt;
➪ the avatar reacts in real time&lt;br&gt;
➪ interactions feel more human&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftr5m0ybpr5hc0b1ylay3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftr5m0ybpr5hc0b1ylay3.png" alt=" " width="800" height="192"&gt;&lt;/a&gt;&lt;br&gt;
Instead of:&lt;/p&gt;

&lt;p&gt;watching an AI video&lt;br&gt;
it feels closer to:&lt;br&gt;
talking with an AI human on a video call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tavus Includes AI Conversation Logic&lt;/strong&gt;&lt;br&gt;
This is the part many people misunderstand.Tavus is not just rendering a face.&lt;/p&gt;

&lt;p&gt;It also helps manage:&lt;/p&gt;

&lt;p&gt;➪ conversation sessions&lt;br&gt;
➪ interaction timing&lt;br&gt;
➪ response behavior&lt;br&gt;
➪ live communication flow&lt;br&gt;
➪ conversational experience&lt;/p&gt;

&lt;p&gt;So developers do not need to build everything from scratch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcblngqnlmesi3jr7fxn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcblngqnlmesi3jr7fxn2.png" alt=" " width="720" height="1080"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Anam — Mainly an Avatar Rendering Platform&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://anam.ai/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Anam Official Website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcdfo9dhn6e7bvjln6ix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcdfo9dhn6e7bvjln6ix.png" alt=" " width="720" height="406"&gt;&lt;/a&gt;&lt;br&gt;
Now let’s talk about Anam.&lt;br&gt;
Anam is actually very impressive visually.&lt;/p&gt;

&lt;p&gt;The avatars often look:&lt;/p&gt;

&lt;p&gt;➪ cinematic&lt;br&gt;
➪ premium&lt;br&gt;
➪ realistic&lt;br&gt;
➪ high-quality&lt;/p&gt;

&lt;p&gt;But here’s the important distinction:&lt;br&gt;
Anam mainly focuses on:&lt;br&gt;
avatar rendering and visual experience.&lt;/p&gt;

&lt;p&gt;Not full conversational AI infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Anam Actually Provides&lt;/strong&gt;&lt;br&gt;
Anam mainly provides:&lt;/p&gt;

&lt;p&gt;➪ realistic avatar rendering&lt;br&gt;
➪ facial animation&lt;br&gt;
➪ lip sync&lt;br&gt;
➪ digital human visuals&lt;br&gt;
➪ avatar streaming&lt;/p&gt;

&lt;p&gt;It focuses heavily on: how the AI human looks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Anam Does NOT Fully Handle&lt;/strong&gt;&lt;br&gt;
Compared to Tavus, Anam does NOT fully provide:&lt;/p&gt;

&lt;p&gt;➪ advanced session management&lt;br&gt;
➪ built-in conversational memory&lt;br&gt;
➪ complete AI orchestration&lt;br&gt;
➪ full conversational flow systems&lt;br&gt;
➪ trained AI behavior systems&lt;br&gt;
➪ ready-made conversational infrastructure&lt;/p&gt;

&lt;p&gt;This means:&lt;br&gt;
developers usually need to build these systems separately.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyloea240rixshjqwfq35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyloea240rixshjqwfq35.png" alt=" " width="720" height="1080"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The REAL Comparison&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j4vog7hy1ymv0kpc8y6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j4vog7hy1ymv0kpc8y6.png" alt=" " width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So Which One Should You Choose?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Choose HeyGen If…&lt;/strong&gt;&lt;br&gt;
You mainly want:&lt;/p&gt;

&lt;p&gt;➪ AI videos&lt;br&gt;
➪ marketing content&lt;br&gt;
➪ training videos&lt;br&gt;
➪ social media content&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Tavus If…&lt;/strong&gt;&lt;br&gt;
You want:&lt;/p&gt;

&lt;p&gt;➪ real-time AI conversations&lt;br&gt;
➪ AI companions&lt;br&gt;
➪ AI tutors&lt;br&gt;
➪ AI support agents&lt;br&gt;
➪ conversational AI humans&lt;/p&gt;

&lt;p&gt;because Tavus provides:&lt;/p&gt;

&lt;p&gt;➪ session handling&lt;br&gt;
➪ conversational systems&lt;br&gt;
➪ memory support&lt;br&gt;
➪ interaction infrastructure&lt;/p&gt;

&lt;p&gt;not just avatars.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose Anam If…&lt;/strong&gt;&lt;br&gt;
You want:&lt;/p&gt;

&lt;p&gt;➪ highly realistic avatar visuals&lt;br&gt;
➪ premium digital humans&lt;br&gt;
➪ custom AI workflows&lt;br&gt;
➪ your own backend AI system&lt;/p&gt;

&lt;p&gt;and you are comfortable building:&lt;/p&gt;

&lt;p&gt;➪ memory systems&lt;br&gt;
➪ conversational orchestration&lt;br&gt;
➪ session management&lt;br&gt;
➪ AI logic&lt;/p&gt;

&lt;p&gt;yourself.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Struggling with Twilio Voice Call Integration in Flutter? twilio_voice_flutter Solves It!</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Wed, 20 May 2026 12:50:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/struggling-with-twilio-voice-call-integration-in-flutter-twiliovoiceflutter-solves-it-6n9</link>
      <guid>https://dev.to/codexlancers/struggling-with-twilio-voice-call-integration-in-flutter-twiliovoiceflutter-solves-it-6n9</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qreoprtmxu81l2hdjag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qreoprtmxu81l2hdjag.png" alt=" " width="700" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The twilio_voice_flutter plugin simplifies integration with Twilio’s Programmable Voice SDK, enabling VoIP calling within your Flutter apps. It supports both iOS and Android, offering an easy-to-use API for managing calls. Ideal for customer service, communication, or any app needing real-time voice, it leverages Twilio’s reliable infrastructure to deliver high-quality VoIP features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting started&lt;/strong&gt;&lt;br&gt;
Add dependency to your pubspec.yaml file &amp;amp; run Pub get&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;twilio_voice_flutter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.0.3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And import package into your class file&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:twilio_voice_flutter/twilio_voice_flutter.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Important Note&lt;/strong&gt;&lt;br&gt;
⚠️ This plugin requires Firebase setup for Twilio voice calls! It uses FCM tokens for handling calls on Android 📲 and VoIP notifications for iOS 📞. Ensure both platforms are properly configured for smooth call functionality. ⚠️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platform Setup&lt;/strong&gt;&lt;br&gt;
Android&lt;br&gt;
To integrate the Twilio Voice plugin into your Android project, follow these steps:&lt;/p&gt;

&lt;p&gt;Open your project’s AndroidManifest.xml file.&lt;br&gt;
Add the following service declaration inside the  tag:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;application&amp;gt;&lt;/span&gt;
    ...
    &lt;span class="nt"&gt;&amp;lt;service&lt;/span&gt;
        &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"com.twilio.voice.flutter.fcm.VoiceFirebaseMessagingService"&lt;/span&gt;
        &lt;span class="na"&gt;android:exported=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
        &lt;span class="na"&gt;android:stopWithTask=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;intent-filter&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"com.google.firebase.MESSAGING_EVENT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/intent-filter&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/service&amp;gt;&lt;/span&gt;
    ...
&lt;span class="nt"&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;iOS&lt;/strong&gt;&lt;br&gt;
To configure your iOS project to support VoIP calls, follow these steps:&lt;/p&gt;

&lt;p&gt;Open your project in Xcode.&lt;br&gt;
Select your project from the Project Navigator.&lt;br&gt;
Go to the Signing &amp;amp; Capabilities tab.&lt;br&gt;
Enable the following Background Modes:&lt;br&gt;
Audio, AirPlay, and Picture in Picture: Allows your app to continue playing audio while in the background.&lt;br&gt;
Voice over IP: Enables your app to receive incoming VoIP calls while in the background.&lt;br&gt;
Ensure that your Info.plist file includes the required keys:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;UIBackgroundModes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;audio&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;voip&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;🔑 Twilio Voice Call Access Token Setup&lt;/strong&gt;&lt;br&gt;
This plugin supports Twilio voice calls for both Android and iOS. To generate the access token and enable Twilio calls, follow the steps in the official Twilio repositories:&lt;/p&gt;

&lt;p&gt;&lt;a href=""&gt;https://github.com/twilio/voice-quickstart-android&lt;/a&gt;&lt;br&gt;
&lt;a href=""&gt;https://github.com/twilio/voice-quickstart-ios&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These repositories provide detailed instructions for generating access tokens and making voice calls through Twilio on both Android and iOS platforms. ⚡ Make sure to follow the steps outlined to successfully integrate Twilio voice functionality into your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up Twilio Token&lt;/strong&gt;&lt;br&gt;
The setTwilioToken function is used to register a user's identity with Twilio Voice using the provided access token. This function handles the retrieval of the Firebase Cloud Messaging (FCM) token on Android devices and registers the user with Twilio Voice.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setTwilioToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_getAccessToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAndroid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;fcmToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getToken&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;TwilioVoiceFlutter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;identity:&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;accessToken:&lt;/span&gt; &lt;span class="n"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;fcmToken:&lt;/span&gt; &lt;span class="n"&gt;fcmToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;TwilioVoiceFlutter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;identity:&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;accessToken:&lt;/span&gt; &lt;span class="n"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;fcmToken:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/DevCodeSpace/twilio_voice_flutter/tree/main/example" rel="noopener noreferrer"&gt;🔗 Visit example for more info… 😊&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;br&gt;
The Twilio Voice Plugin for Flutter enables seamless integration of voice-over-IP (VoIP) calling into your Flutter applications. Below are the key features supported by this plugin:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1su1a714dny52sw54blz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1su1a714dny52sw54blz.png" alt=" " width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. VoIP Call Management&lt;/strong&gt;&lt;br&gt;
Initiate Calls: Easily start a VoIP call to any recipient using the makeCall method, with the ability to pass custom call data.&lt;/p&gt;

&lt;p&gt;Initiate Calls: Easily start a VoIP call to any recipient using the makeCall method, with the ability to pass custom call data.&lt;br&gt;
Receive Incoming Calls: Handle incoming call invites via push notifications, and answer calls using built-in CallKit support on iOS.&lt;br&gt;
Call Status Notifications: Stay updated on call status changes such as ringing, connecting, and disconnecting through Flutter MethodChannel callbacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. In-Call Controls&lt;/strong&gt;&lt;br&gt;
Mute/Unmute Calls: Toggle the mute status of the ongoing call using the toggleMute method. Check if the call is currently muted with the isMuted method.&lt;br&gt;
Speakerphone Control: Switch between the device’s built-in speaker and receiver during an ongoing call using toggleSpeaker. Verify the current audio route with isSpeaker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. CallKit Integration for iOS&lt;/strong&gt;&lt;br&gt;
CallKit Support: Utilize native CallKit functionality on iOS for managing incoming and outgoing VoIP calls, ensuring a familiar user experience.&lt;br&gt;
Incoming Call Handling: Report incoming calls to CallKit, allowing the system to display the native call UI and handle interruptions correctly.&lt;br&gt;
Background VoIP Support: Ensure your app can receive VoIP calls while in the background by enabling the necessary background modes and configuring the Info.plist accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Push Notification Support&lt;/strong&gt;&lt;br&gt;
VoIP Push Notifications: Register and handle VoIP push notifications via Firebase Cloud Messaging (FCM) on Android and Apple Push Notification service (APNs) on iOS.&lt;br&gt;
Push Credential Management: Manage device and access tokens required for receiving VoIP push notifications, ensuring reliable communication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. DTMF (Dual-tone Multi-frequency) Signaling&lt;/strong&gt;&lt;br&gt;
Send DTMF Digits: During an active call, send DTMF tones (e.g., for interacting with automated phone systems) using the sendDigits method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Contact Management&lt;/strong&gt;&lt;br&gt;
Custom Contact Data: Store and retrieve custom contact data (like display names and photo URLs) to enhance the calling experience with personalized information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Persistent Data Storage&lt;/strong&gt;&lt;br&gt;
Token and Contact Data Persistence: Securely store and retrieve access tokens and contact data using UserDefaults on iOS to maintain state across app sessions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Call Handling with Error Management&lt;/strong&gt;&lt;br&gt;
Graceful Error Handling: Comprehensive error handling ensures that issues like token expiration or failed call connections are managed and reported to the user effectively.&lt;br&gt;
With these features, the Twilio Voice Plugin provides a robust foundation for integrating voice communication into your Flutter applications, supporting a wide range of use cases from customer support to in-app &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function Overview&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;registerTwilio():&lt;/strong&gt; Registers the device with Twilio using the access token and device token for VoIP push notifications.&lt;br&gt;
&lt;strong&gt;unregisterTwilio():&lt;/strong&gt; Unregisters the device from Twilio VoIP push notifications, removing the access token and device token.&lt;br&gt;
&lt;strong&gt;makeCall(String to):&lt;/strong&gt; Initiates a voice call to the specified recipient. If an active call exists, it returns an error.&lt;br&gt;
&lt;strong&gt;toggleMute():&lt;/strong&gt; Toggles the mute status of the ongoing call. Notifies the Flutter side of the change.&lt;br&gt;
&lt;strong&gt;isMuted():&lt;/strong&gt; Returns the current mute status of the ongoing call.&lt;br&gt;
&lt;strong&gt;toggleSpeaker():&lt;/strong&gt; Toggles the speaker mode during an ongoing call. Notifies the Flutter side of the change.&lt;br&gt;
&lt;strong&gt;isSpeaker() -&amp;gt; Bool:&lt;/strong&gt; Checks if the speaker mode is currently active.&lt;br&gt;
&lt;strong&gt;hangUp():&lt;/strong&gt; Ends the current call. If no active call exists, it clears the call-related data.&lt;br&gt;
&lt;strong&gt;activeCall():&lt;/strong&gt; Returns details of the active call if one exists.&lt;br&gt;
sendDigits(String digits): Sends DTMF digits during an active call.&lt;br&gt;
For more information, check out the below link&lt;/p&gt;

&lt;p&gt;&lt;a href="http://pub.dev/packages/twilio_voice_flutter" rel="noopener noreferrer"&gt;twilio_voice_flutter | Flutter package&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://pub.dev/packages/twilio_voice_flutter" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub.dev%2Fstatic%2Fhash-fsujdolb%2Fimg%2Fpub-dev-icon-cover-image.png" height="400" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://pub.dev/packages/twilio_voice_flutter" rel="noopener noreferrer" class="c-link"&gt;
            twilio_voice_flutter | Flutter package
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Voice SDK to allow adding voice-over-IP (VoIP) calling into your Flutter applications.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub.dev%2Fstatic%2Fhash-fsujdolb%2Fimg%2Fflutter-logo-32x32.png" width="32" height="32"&gt;
          pub.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhgtjdpvzoy68xxb6yv3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhgtjdpvzoy68xxb6yv3h.png" alt=" " width="300" height="168"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Thanks for reading! If this post was helpful, feel free to share it and follow for more Flutter tips and tutorials. Keep coding and stay awesome!&lt;/p&gt;

</description>
      <category>api</category>
      <category>flutter</category>
      <category>mobile</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Struggling with Icloud Data Sync Issues? Let iCloud_Storage_Sync Handle It!</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Tue, 19 May 2026 12:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/struggling-with-icloud-data-sync-issues-let-icloudstoragesync-handle-it-2ib8</link>
      <guid>https://dev.to/codexlancers/struggling-with-icloud-data-sync-issues-let-icloudstoragesync-handle-it-2ib8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9e27e29bheidppfxzbly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9e27e29bheidppfxzbly.png" alt=" " width="720" height="240"&gt;&lt;/a&gt;&lt;br&gt;
In the ever-evolving world of mobile app development, providing a seamless user experience across multiple devices is no longer a luxury — it’s a necessity. Enter the iCloud_Storage_Sync plugin, a game-changing solution for Flutter developers looking to harness the power of iCloud in their iOS applications. This comprehensive guide will walk you through everything you need to know about this powerful tool and how it can elevate your app to new heights.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛠 Setting Up iCloud Container: A Step-by-Step Guide&lt;/strong&gt;&lt;br&gt;
Before diving into the features and implementation of the iCloud_Storage_Sync plugin, it’s crucial to properly set up your iCloud Container. Here’s a detailed walkthrough:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;👤 &lt;strong&gt;Access Your Apple Developer Account&lt;/strong&gt; Log in and navigate to ‘Certificates, IDs &amp;amp; Profiles’.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🆔 &lt;strong&gt;Create Necessary IDs&lt;/strong&gt; Set up an App ID (if you haven’t already) and create an iCloud Containers ID.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfb0s18niyuxzz8uy8zu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfb0s18niyuxzz8uy8zu.png" alt=" " width="720" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🔗 &lt;strong&gt;Link iCloud Container to Your App&lt;/strong&gt; Assign the iCloud Container to your App ID in the Apple Developer portal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gcygpsixrblmzjj6h2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gcygpsixrblmzjj6h2i.png" alt=" " width="720" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;💻 &lt;strong&gt;Configure Xcode&lt;/strong&gt; Enable the iCloud capability in your Xcode project and select your container.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xps56dxt4ewmfvg74ph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xps56dxt4ewmfvg74ph.png" alt=" " width="720" height="477"&gt;&lt;/a&gt;&lt;br&gt;
Following these steps ensures that your app is properly set up to use iCloud storage, paving the way for seamless integration with the iCloud_Storage_Sync plugin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🌟 Introduction: Bridging Flutter and iCloud&lt;/strong&gt;&lt;br&gt;
The iCloud_Storage_Sync plugin is designed to simplify the integration of iCloud storage capabilities into your Flutter iOS apps. By leveraging this plugin, you can offer your users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔄 Effortless backup and synchronization of app data&lt;/li&gt;
&lt;li&gt;📱💻 A consistent user experience across all their Apple devices&lt;/li&gt;
&lt;li&gt;🔒 Secure storage and retrieval of important information&lt;/li&gt;
&lt;li&gt;☁️ Seamless integration with the iCloud ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you’re building a note-taking app, a photo storage solution, or any application that benefits from cloud synchronization, iCloud_Storage_Sync provides the tools you need to create a robust, user-friendly experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✨ Features: A Deep Dive&lt;/strong&gt;&lt;br&gt;
Let’s explore the core features that make iCloud_Storage_Sync a must-have for your Flutter iOS project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;📂** Get iCloud Files**&lt;br&gt;
Retrieve files stored in iCloud with ease. This feature allows your app to access user data across devices, ensuring a consistent experience no matter where they log in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⬆️** Upload Files to iCloud**&lt;br&gt;
Empower your users to store their important files securely in the cloud. With simple upload functionality, you can offer peace of mind and accessibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✏️ &lt;strong&gt;Rename iCloud Files&lt;/strong&gt;&lt;br&gt;
Provide users with the flexibility to organize their cloud storage. The ability to rename files directly within your app adds a layer of convenience to file management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🗑️ &lt;strong&gt;Delete iCloud Files&lt;/strong&gt;&lt;br&gt;
Keep cloud storage tidy with straightforward file deletion. This feature ensures users can manage their storage space efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;↔️ &lt;strong&gt;Move iCloud Files&lt;/strong&gt;&lt;br&gt;
Enhance file organization by allowing users to move files between folders in their iCloud storage, all from within your app.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These features combine to create a comprehensive iCloud management system within your Flutter app, offering users the full power of cloud storage at their fingertips.&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Getting Started: From Installation to Implementation&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Step 1: 🛠️ Installation&lt;/strong&gt;&lt;br&gt;
Begin by adding the iCloud_Storage_Sync plugin to your ‘pubspec.yaml’ file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;icloud_storage_sync&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 2: ⚙️ Install the Plugin&lt;/strong&gt;&lt;br&gt;
Run the following command in your terminal:&lt;/p&gt;

&lt;p&gt;“flutter pub get”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: 💻 Usage in Your Dart Code&lt;/strong&gt;&lt;br&gt;
Import the plugin in your Dart files:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:icloud_storage_sync/icloud_storage_sync.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With these simple steps, you’re ready to start integrating iCloud functionality into your Flutter app.&lt;/p&gt;

&lt;p&gt;📋 &lt;strong&gt;Prerequisites: Setting the Stage for Success&lt;/strong&gt;&lt;br&gt;
Before diving into implementation, ensure you have the following in place:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xza2l9ts1ffsk8nl13o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xza2l9ts1ffsk8nl13o.png" alt=" " width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;☑️ An active Apple Developer account&lt;/li&gt;
&lt;li&gt;☑️ A registered App ID and iCloud Container ID&lt;/li&gt;
&lt;li&gt;☑️ iCloud capability enabled and assigned to your app&lt;/li&gt;
&lt;li&gt;☑️ iCloud capability properly configured in Xcode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧰 &lt;strong&gt;API Examples: Bringing iCloud to Life in Your App&lt;/strong&gt;&lt;br&gt;
Let’s explore how to implement each of the core features in your Flutter app:&lt;/p&gt;

&lt;p&gt;📥 &lt;strong&gt;Getting iCloud Files&lt;/strong&gt;&lt;br&gt;
Retrieve a list of files stored in iCloud:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CloudFiles&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getCloudFiles&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;icloudSyncPlugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCloudFiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;containerId:&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;📤 &lt;strong&gt;Uploading Files to iCloud&lt;/strong&gt;&lt;br&gt;
Upload files to iCloud with progress tracking:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;destinationRelativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="n"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;onProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;icloudSyncPlugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="nl"&gt;containerId:&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;filePath:&lt;/span&gt; &lt;span class="n"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;destinationRelativePath:&lt;/span&gt; &lt;span class="n"&gt;destinationRelativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;onProgress:&lt;/span&gt; &lt;span class="n"&gt;onProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;🏷️ &lt;strong&gt;Renaming iCloud Files&lt;/strong&gt;&lt;br&gt;
Allow users to rename their files in iCloud:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;newName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;icloudSyncPlugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="nl"&gt;containerId:&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;relativePath:&lt;/span&gt; &lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;newName:&lt;/span&gt; &lt;span class="n"&gt;newName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;🗑️ &lt;strong&gt;Deleting iCloud Files&lt;/strong&gt;&lt;br&gt;
Implement file deletion functionality:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;icloudSyncPlugin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="nl"&gt;containerId:&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;relativePath:&lt;/span&gt; &lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;🔀 &lt;strong&gt;Moving iCloud Files&lt;/strong&gt;&lt;br&gt;
Enable users to organize their files by moving them within iCloud:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fromRelativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;toRelativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;IcloudSyncPlatform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="nl"&gt;containerId:&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;fromRelativePath:&lt;/span&gt; &lt;span class="n"&gt;fromRelativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="nl"&gt;toRelativePath:&lt;/span&gt; &lt;span class="n"&gt;toRelativePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These code snippets demonstrate the simplicity and power of the iCloud_Storage_Sync plugin. With just a few lines of code, you can implement robust cloud storage features in your Flutter app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 Real-World Applications: Unleashing the Potential&lt;/strong&gt;&lt;br&gt;
The iCloud_Storage_Sync plugin opens up a world of possibilities for your Flutter iOS app. Here are some practical applications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;📝 &lt;strong&gt;Note-Taking Apps:&lt;/strong&gt; Sync notes across devices, ensuring users always have access to their latest thoughts.&lt;/li&gt;
&lt;li&gt;📸 &lt;strong&gt;Photo Storage Solutions:&lt;/strong&gt; Offer seamless backup and access to photos across all Apple devices.&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;Document Management:&lt;/strong&gt; Create a robust system for storing, organizing, and accessing important documents in the cloud.&lt;/li&gt;
&lt;li&gt;🎮 &lt;strong&gt;Game Progress Sync:&lt;/strong&gt; Keep game saves and progress in sync, allowing users to pick up where they left off on any device.&lt;/li&gt;
&lt;li&gt;📅 &lt;strong&gt;Productivity Apps:&lt;/strong&gt; Synchronize tasks, calendars, and reminders to keep users organized across their Apple ecosystem.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By implementing iCloud sync, you’re not just adding a feature — you’re enhancing the overall user experience and adding significant value to your app.&lt;/p&gt;

&lt;p&gt;🤝** Contributing: Join the Community**&lt;br&gt;
The iCloud_Storage_Sync plugin is an open-source project, and we welcome contributions from the developer community. Whether you’re fixing bugs, improving documentation, or adding new features, your input is valuable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check out our [GitHub repository]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;icloud_storage_sync to get started. Don’t forget to review our contribution guidelines to ensure a smooth collaboration process.&lt;/p&gt;

&lt;p&gt;🌟** Conclusion: Elevate Your Flutter App with iCloud Integration**&lt;br&gt;
The iCloud_Storage_Sync plugin represents a significant leap forward for Flutter developers looking to create seamless, cloud-connected iOS applications. By leveraging the power of iCloud, you can offer your users a premium experience that keeps their data secure, accessible, and in sync across all their Apple devices.&lt;/p&gt;

&lt;p&gt;From simple file storage to complex data synchronization, this plugin provides the tools you need to take your app to the next level. As the mobile app landscape continues to evolve, staying ahead of the curve with features like cloud integration is crucial for success.&lt;/p&gt;

&lt;p&gt;We invite you to explore the iCloud_Storage_Sync plugin, integrate it into your projects, and experience firsthand the power of seamless cloud synchronization in your Flutter iOS apps. Your users — and your app’s success — will thank you.&lt;/p&gt;

&lt;p&gt;Ready to get started? Download the plugin now and join the ranks of developers offering top-tier cloud integration in their Flutter apps!&lt;/p&gt;

&lt;p&gt;For more information, check out the below link&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://pub.dev/packages/icloud_storage_sync?source=post_page-----d6acaade8a59---------------------------------------" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub.dev%2Fstatic%2Fhash-fsujdolb%2Fimg%2Fpub-dev-icon-cover-image.png" height="400" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://pub.dev/packages/icloud_storage_sync?source=post_page-----d6acaade8a59---------------------------------------" rel="noopener noreferrer" class="c-link"&gt;
            icloud_storage_sync | Flutter package
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Easily sync and secure your app's data with the iCloud Sync Flutter plugin for seamless iCloud integration.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub.dev%2Fstatic%2Fhash-fsujdolb%2Fimg%2Fflutter-logo-32x32.png" width="32" height="32"&gt;
          pub.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67maykwvn4hbxl9d5jl8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67maykwvn4hbxl9d5jl8.png" alt=" " width="300" height="168"&gt;&lt;/a&gt;&lt;br&gt;
Thanks for reading! If this post was helpful, feel free to share it and follow for more Flutter tips and tutorials. Keep coding and stay awesome!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>ios</category>
      <category>mobile</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Effortless Dart Coding with dart_extensions_pro</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Mon, 18 May 2026 04:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/effortless-dart-coding-with-dartextensionspro-2bhg</link>
      <guid>https://dev.to/codexlancers/effortless-dart-coding-with-dartextensionspro-2bhg</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcq72b4rutz2cw9t8x3vz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcq72b4rutz2cw9t8x3vz.png" alt=" "&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
Introducing dart_extensions_pro a Dart package that offers a collection of handy extensions and helper functions designed to enhance the development process. By simplifying common tasks and providing streamlined solutions, it allows developers to write code more efficiently and focus on building features rather than repetitive tasks. Ideal for improving productivity, this package is a valuable tool for both novice and experienced programmers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;br&gt;
📊 &lt;strong&gt;Comparison:&lt;/strong&gt; Simplify comparison operations with intuitive extension methods.&lt;/p&gt;

&lt;p&gt;📅** Date Handling:** Effortlessly manage date and time with a variety of helpful functions.&lt;/p&gt;

&lt;p&gt;✍️ &lt;strong&gt;String Utilities:&lt;/strong&gt; Enhance string manipulation with powerful utility functions.&lt;/p&gt;

&lt;p&gt;📋 &lt;strong&gt;List Enhancements:&lt;/strong&gt; Improve list handling with convenient extensions for common operations.&lt;/p&gt;

&lt;p&gt;🧭 &lt;strong&gt;Navigation:&lt;/strong&gt; Streamline navigation tasks with specialized navigation functions.&lt;/p&gt;

&lt;p&gt;👆 &lt;strong&gt;Tap Gestures:&lt;/strong&gt; Easily handle tap gestures to improve user interaction.&lt;/p&gt;

&lt;p&gt;🔁 &lt;strong&gt;Iterable Enhancements:&lt;/strong&gt; Optimize iterable processing with enhanced methods.&lt;/p&gt;

&lt;p&gt;🎨 &lt;strong&gt;Color Conversion:&lt;/strong&gt; Simplify color manipulations and conversions with dedicated functions.&lt;/p&gt;

&lt;p&gt;🔢 &lt;strong&gt;Number Utilities:&lt;/strong&gt; Access a range of number-related utilities for calculations and formatting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgv4n2y7voo919ahz44o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqgv4n2y7voo919ahz44o.png" alt=" "&gt;&lt;/a&gt;&lt;br&gt;
🛠️ &lt;strong&gt;Utility Functions:&lt;/strong&gt; Utilize various handy utility functions to simplify your coding experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;br&gt;
Add dependency to your pubspec.yaml file &amp;amp; run Pub get&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dart_extensions_pro&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And import package into your class file&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:dart_extensions_pro/dart_extensions_pro.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;Analytics&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Visit EXTENSIONS.md for a complete list of all the available extensions.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Extensions:                    271
Helper Classes:                7
Helper Functions &amp;amp; Getters:    21
Typedefs:                      7
Mixins:                        2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Here’s a quick preview of dart_extensions_pro,&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;String extension&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="s"&gt;'hello'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;iscapitalize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Capitalizes first letter // Hello&lt;/span&gt;
&lt;span class="s"&gt;'Copy this text'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;copyTo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Copies string to clipboard&lt;/span&gt;
&lt;span class="s"&gt;'test@example.com'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isValidEmail&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Checks if valid email // true&lt;/span&gt;
&lt;span class="s"&gt;'flutter'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Reverses string // rettulf&lt;/span&gt;
&lt;span class="s"&gt;'madam'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isPalindrome&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Checks for palindrome // true&lt;/span&gt;
&lt;span class="s"&gt;'flutter example'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toCamelCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Converts to camel case // FlutterExample&lt;/span&gt;
&lt;span class="s"&gt;'{"name": "Flutter"}'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;decodeJson&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Parses JSON string to map // {name: Flutter}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Comparison extension&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// true, checks if 5 is greater than 3&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// true, checks if 3 is less than 5&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// true, checks if 5 is equal to 5&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true, checks if 3 is less than or equal to 3&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true, checks if 5 is greater than or equal to 3&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// true, checks if 5 is not equal to 3&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Date extension&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSameDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  &lt;span class="c1"&gt;// true, checks if today matches the provided date&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isToday&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// true, checks if today is today&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isTomorrow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// true, checks if today is tomorrow (unlikely)&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wasYesterday&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// true, checks if today is yesterday (false)&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// adds 5 days to the current date&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addMonths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// adds 3 months to the current date&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addYears&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// adds 2 years to the current date&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subtractDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// subtracts 7 days from the current date&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subtractMonths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// subtracts 1 month from the current date&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subtractYears&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// subtracts 1 year from the current date&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;List extension&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// [1, 2, 3, 4], appends 4 to the list using the `&amp;lt;&amp;lt;` operator&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replaceFirstWhere&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// true, replaces the first occurrence of 2 with 10&lt;/span&gt;
&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replaceLastWhere&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// true, replaces the last item greater than 1 with 20&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Navigation extension&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Navigates to `MyPage` using `to()`&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toNamed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/home'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Navigates to the named route '/home' using `toNamed()`&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;back&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Pops the current route using `back()`&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;backUntil&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isFirst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Pops routes until the first one using `backUntil()`&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toWithReplace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AnotherPage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Replaces current route with `AnotherPage` using `toWithReplace()`&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replaceWithNamed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/dashboard'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Replaces the current route with named route '/dashboard' using `replaceWithNamed()`&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toAndRemoveAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Navigates to `HomePage` and removes all previous routes using `toAndRemoveAll()`&lt;/span&gt;
&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toNamedAndRemoveAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/login'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Navigates to named route '/login' and removes all previous routes using `toNamedAndRemoveAll()`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Gesture extension&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onInkTap&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Tapped!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Adds an ink splash effect with `onInkTap()`&lt;/span&gt;
&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onTap&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Tapped!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Adds a basic tap gesture with `onTap()`&lt;/span&gt;
&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onDoubleTap&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Double Tapped!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Adds a double-tap gesture with `onDoubleTap()`&lt;/span&gt;
&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onTapCancel&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Tap Cancelled!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Adds a tap cancel gesture with `onTapCancel()`&lt;/span&gt;
&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onLongPress&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Long Pressed!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Adds a long press gesture with `onLongPress()`&lt;/span&gt;
&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onTapDown&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Tap Down!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Adds a tap down gesture with `onTapDown()`&lt;/span&gt;
&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;onScaleStart:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Scale Started!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nl"&gt;onScaleUpdate:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Scaling!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nl"&gt;onScaleEnd:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;'Scale Ended!'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logMsg&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Adds a scale gesture with `onScale()`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Iterable extension&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastElementIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Returns the index of the last element or -1 if empty.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasSingleElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Checks if the iterable has exactly one element.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addAllMatchingTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEven&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Adds elements matching the predicate to the target list.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;whereFilter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEven&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Filters elements matching the predicate.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;whereFilterIndexed&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Filters elements with their index.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapTransform&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  &lt;span class="c1"&gt;// Transforms each element and maps to a new iterable.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;skipElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Skips the first 2 elements.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;takeLastElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Takes the last 2 elements.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;skipWhileElements&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Skips elements while the predicate is true.&lt;/span&gt;
&lt;span class="n"&gt;iterable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;skipLastElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Skips the last 2 elements.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Color conversion&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toColor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Converts a hex color string to a Color object, assuming full opacity.&lt;/span&gt;
&lt;span class="n"&gt;HexColor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getColorFromHex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hexColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Converts a hex color string to an integer color value, adding alpha if missing.&lt;/span&gt;
&lt;span class="n"&gt;HexColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hexColor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Creates a HexColor instance from a hex color string.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Number conversion&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;
&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;negative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Converts positive numbers to their negative counterparts.&lt;/span&gt;
&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isBetween&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;inclusive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;  &lt;span class="c1"&gt;// Checks if [this] is between [value1] and [value2], inclusive if [inclusive] is true.&lt;/span&gt;
&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;roundToDecimals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decimalPlaces&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Rounds the number to [decimalPlaces] decimal places.&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asRadians&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Converts degrees to radians.&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asDegrees&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Converts radians to degrees.&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upperBound&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exclusive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;  &lt;span class="c1"&gt;// Limits the value to [upperBound], exclusive if [exclusive] is true.&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;minm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lowerBound&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exclusive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;  &lt;span class="c1"&gt;// Ensures the value is not less than [lowerBound], exclusive if [exclusive] is true.&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clampAtMin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lowerBound&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Ensures the value is not below [lowerBound].&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clampAtMax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upperBound&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Ensures the value does not exceed [upperBound].&lt;/span&gt;
&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orZero&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Returns this value or 0 if null.&lt;/span&gt;
&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orOne&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Returns this value or 1 if null.&lt;/span&gt;
&lt;span class="kt"&gt;num&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Returns this value or [value] if null.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Utility conversion&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isWhole&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Checks if the value is a whole number.&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;roundToPrecision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nthPosition&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Rounds the value to [precision] decimal places.&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isCloseTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;precision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0e-8&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;  &lt;span class="c1"&gt;// Checks if the value is close to [other] within [precision].&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;randomDouble&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;  &lt;span class="c1"&gt;// Generates a random double between 0.0 (inclusive) and 1.0 (exclusive).&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;inYears&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Returns the number of whole years spanned by this [Duration].&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isInYears&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Returns `true` if the [Duration] is equal to or longer than one year.&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;absoluteSeconds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Returns the number of seconds remaining after accounting for whole minutes.&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;operator&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&amp;lt;(&lt;/span&gt;&lt;span class="n"&gt;MapEntry&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Inserts a [MapEntry] into the map using the `&amp;lt;&amp;lt;` operator.&lt;/span&gt;
&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toJson&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Converts the map into a JSON string.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For more information, check out the below link&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://pub.dev/packages/dart_extensions_pro?source=post_page-----f5961086cf63---------------------------------------" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub.dev%2Fstatic%2Fhash-fsujdolb%2Fimg%2Fpub-dev-icon-cover-image.png" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://pub.dev/packages/dart_extensions_pro?source=post_page-----f5961086cf63---------------------------------------" rel="noopener noreferrer" class="c-link"&gt;
            dart_extensions_pro | Flutter package
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            A Dart package that provides handy extensions and helper functions, designed to simplify and speed up development, making coding more efficient and streamlined.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub.dev%2Fstatic%2Fhash-fsujdolb%2Fimg%2Fflutter-logo-32x32.png"&gt;
          pub.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7gwyo2qj7gfbl03y5yx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7gwyo2qj7gfbl03y5yx.png" alt=" "&gt;&lt;/a&gt;&lt;br&gt;
Thanks for reading! If this post was helpful, feel free to share it and follow for more Flutter tips and tutorials. Keep coding and stay awesome!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Flutter Zoom Meeting Wrapper</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Fri, 15 May 2026 12:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/flutter-zoom-meeting-wrapper-4hb</link>
      <guid>https://dev.to/codexlancers/flutter-zoom-meeting-wrapper-4hb</guid>
      <description>&lt;p&gt;In today’s connected world, video conferencing has become an essential part of our daily lives. As mobile app developers, integrating reliable video conferencing capabilities can significantly enhance the user experience of your applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhoimbih8xdy0nqumbtg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhoimbih8xdy0nqumbtg.png" alt=" " width="720" height="386"&gt;&lt;/a&gt;&lt;br&gt;
The &lt;strong&gt;Flutter Zoom Meeting Wrapper&lt;/strong&gt; is a powerful Flutter plugin that allows you to seamlessly integrate the Zoom Meeting SDK into your Flutter applications. This means your users can join and participate in Zoom meetings directly within your app without ever needing to switch to the Zoom application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;br&gt;
This plugin offers a range of capabilities to enhance your Flutter application:&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Seamless Integration:&lt;/strong&gt; Easy integration with the Zoom Meeting SDK&lt;br&gt;
🔄 &lt;strong&gt;Simple Initialization:&lt;/strong&gt; Initialize the SDK using a JWT token&lt;br&gt;
🎯 &lt;strong&gt;In-App Experience:&lt;/strong&gt; Join meetings directly within your app (no Zoom app required)&lt;br&gt;
📱 &lt;strong&gt;Platform Support:&lt;/strong&gt; Complete Android platform compatibility&lt;br&gt;
🔊 &lt;strong&gt;Rich Meeting Experience:&lt;/strong&gt; Full audio and video meeting functionality&lt;br&gt;
🔐 &lt;strong&gt;Secure Authentication:&lt;/strong&gt; Robust security through JWT authentication flow&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Installation&lt;/strong&gt;&lt;br&gt;
To begin using the Flutter Zoom Meeting Wrapper in your project, add the following to your pubspec.yaml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;flutter_zoom_meeting_wrapper&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run flutter pub get to install the package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mandatory Zoom SDK Setup&lt;/strong&gt;&lt;br&gt;
For the plugin to function correctly, you need to set up the Zoom SDK:&lt;/p&gt;

&lt;p&gt;Download the Zoom SDK ZIP from &lt;a href="https://drive.google.com/file/d/1aKhrS5JCVSxvQkfdXH0N1h45Lk2gt6P9/view" rel="noopener noreferrer"&gt;this link&lt;/a&gt;&lt;br&gt;
Extract the ZIP file after downloading&lt;br&gt;
Copy the libs folder and paste it inside your Flutter pub-cache directory at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.pub-cache/hosted/pub.dev/flutter_zoom_meeting_wrapper-0.0.1/android/

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: Replace 0.0.1 with the version you're using, if different.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Alternatively, run the following command to open the folder directly:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;open ~/.pub-cache/hosted/pub.dev/flutter_zoom_meeting_wrapper-0.0.1/android

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Important: The libs folder must be placed in the correct location for the plugin to function properly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up Zoom API Credentials&lt;/strong&gt;&lt;br&gt;
To use the Zoom Meeting SDK in your application, you’ll need to:&lt;/p&gt;

&lt;p&gt;Create a Zoom Developer Account at &lt;a href="https://marketplace.zoom.us/" rel="noopener noreferrer"&gt;Zoom Marketplace&lt;/a&gt;&lt;br&gt;
Create a new app in the Zoom Marketplace&lt;br&gt;
Obtain your API Key and API Secret from the app credentials page&lt;br&gt;
Use these credentials to generate your JWT token&lt;br&gt;
&lt;strong&gt;Generating a JWT Token&lt;/strong&gt;&lt;br&gt;
You can generate a Zoom JWT token using jwt.io with the following payload and signature:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjc23oxec6gemc6df5bjl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjc23oxec6gemc6df5bjl.png" alt=" " width="800" height="192"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Payload:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;json&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"appKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ZOOM-CLIENT-KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ANY-TIME-STAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"exp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ANY-TIME-STAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;greater&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;iat&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tokenExp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ANY-TIME-STAMP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;greater&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;than&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;iat&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify Signature:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  "ZOOM-CLIENT-SECRET"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Implementation Guide&lt;br&gt;
Initializing the SDK&lt;/strong&gt;&lt;br&gt;
First, initialize the Zoom SDK with your JWT token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter_zoom_meeting_wrapper/flutter_zoom_meeting_wrapper.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize Zoom SDK&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isInitialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ZoomMeetingWrapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initZoom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwtToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Joining a Meeting&lt;/strong&gt;&lt;br&gt;
Once initialized, you can join a Zoom meeting with this simple code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;joinSuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ZoomMeetingWrapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;joinMeeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;meetingId:&lt;/span&gt; &lt;span class="s"&gt;"your_meeting_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;meetingPassword:&lt;/span&gt; &lt;span class="s"&gt;"meeting_password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;displayName:&lt;/span&gt; &lt;span class="s"&gt;"Your Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Troubleshooting Common Issues&lt;/strong&gt;&lt;br&gt;
When implementing the Flutter Zoom Meeting Wrapper, you might encounter these common issues:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JWT Token Invalid:&lt;/strong&gt; Ensure your API Key and Secret are correct, and verify that your system time is accurate.&lt;br&gt;
&lt;strong&gt;Failed to initialize SDK:&lt;/strong&gt; Check that you have a stable internet connection and are using a valid JWT token.&lt;br&gt;
&lt;strong&gt;Cannot join meeting:&lt;/strong&gt; Double-check that the meeting ID and password are correct.&lt;br&gt;
&lt;strong&gt;Current Limitations&lt;/strong&gt;&lt;br&gt;
While the Flutter Zoom Meeting Wrapper provides powerful functionality, be aware of these current limitations:&lt;/p&gt;

&lt;p&gt;🖼️ Custom UI overlays are not supported in the current version&lt;br&gt;
📹 Meeting recording functionality is not available in this plugin&lt;br&gt;
🖥️ Screen sharing capabilities are limited to platform capabilities&lt;br&gt;
&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
The Flutter Zoom Meeting Wrapper offers a straightforward way to integrate Zoom’s powerful meeting capabilities into your Flutter applications. With minimal setup and easy-to-use API, you can enhance your app with professional video conferencing features.&lt;/p&gt;

&lt;p&gt;By providing users with the ability to join meetings without leaving your app, you create a more seamless and integrated experience that keeps users engaged with your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8unuv2bsp8jmmtzmiae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8unuv2bsp8jmmtzmiae.png" alt=" " width="400" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>flutter</category>
      <category>mobile</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Flutter + Firebase Cloud Functions: Complete Guide with Real Examples 🚀</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Wed, 13 May 2026 12:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/flutter-firebase-cloud-functions-complete-guide-with-real-examples-7h2</link>
      <guid>https://dev.to/codexlancers/flutter-firebase-cloud-functions-complete-guide-with-real-examples-7h2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
Building modern mobile apps requires more than just a beautiful UI — you also need a reliable backend. This is where F**lutter and Firebase Cloud **Functions become a powerful combination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flutter&lt;/strong&gt; is a UI toolkit by Google that allows you to build natively compiled apps for mobile, web, and desktop using a single codebase.&lt;br&gt;
&lt;strong&gt;Firebase Cloud Functions&lt;/strong&gt; is a serverless backend solution that lets you run code in response to events without managing servers.&lt;br&gt;
👉 When you combine them, you get:&lt;/p&gt;

&lt;p&gt;A fast, scalable frontend (Flutter)&lt;br&gt;
A powerful, secure backend (Cloud Functions)&lt;br&gt;
This guide will walk you through everything — from setup to real-world examples — in a simple and practical way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use Flutter + Firebase Cloud Functions?&lt;/strong&gt;&lt;br&gt;
🔥 &lt;strong&gt;Key Benefits&lt;/strong&gt;&lt;br&gt;
Feature Benefit Serverless backend No need to manage serversReal-time integrationWorks seamlessly with Firestore Scalability Automatically scales with usersSecurityBackend logic stays hiddenCost-effectivePay only for usage&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;br&gt;
Here are some real-world scenarios where this combination shines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Secure Backend Logic&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Payment verification&lt;/li&gt;
&lt;li&gt;User authentication checks&lt;/li&gt;
&lt;li&gt;Role-based access control&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Notifications System&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Send push notifications when data changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trigger alerts on user actions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Processing&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatically process uploaded data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean and transform Firestore entries&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Third-Party API Integration&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call external APIs securely (without exposing keys)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scheduled Jobs&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Daily reports&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleanup tasks&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step-by-Step Setup&lt;/strong&gt;&lt;br&gt;
Let’s set up everything from scratch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Setup Flutter Project&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter create my_app
&lt;span class="nb"&gt;cd &lt;/span&gt;my_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Setup Firebase&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Firebase Console&lt;/li&gt;
&lt;li&gt;Create a project&lt;/li&gt;
&lt;li&gt;Add Android/iOS app&lt;/li&gt;
&lt;li&gt;Download config files:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;google-services.json (Android)&lt;/li&gt;
&lt;li&gt;GoogleService-Info.plist (iOS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add Firebase to Flutter&lt;/strong&gt;&lt;br&gt;
Add dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;firebase_core&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^latest&lt;/span&gt;
  &lt;span class="na"&gt;cloud_firestore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize Firebase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;WidgetsFlutterBinding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ensureInitialized&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Firebase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Setup Firebase CLI&lt;/strong&gt;&lt;br&gt;
Install CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; firebase-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase init functions

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript or TypeScript&lt;/li&gt;
&lt;li&gt;ESLint (optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Write Your First Cloud Function&lt;/strong&gt;&lt;br&gt;
Example: Trigger when a user is created in Firestore&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase-functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUserCreate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users/{userId}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New user created:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase deploy &lt;span class="nt"&gt;--only&lt;/span&gt; functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-World Examples 🔥&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Example 1: Send Push Notification on New Message&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Cloud Function&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendNotification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;messages/{id}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New Message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;sendToTopic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;allUsers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flutter Side&lt;/strong&gt;&lt;br&gt;
Subscribe to topic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subscribeToTopic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"allUsers"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F13ckgaxu7lulwggq827n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F13ckgaxu7lulwggq827n.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 2: Secure Payment Verification&lt;/strong&gt;&lt;br&gt;
👉 Never verify payments on the client side!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud Function&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verifyPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paymentId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Call payment gateway API&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// simulate&lt;/span&gt;

   &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HttpsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;failed-precondition&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid payment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Flutter Call&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;callable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FirebaseFunctions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;httpsCallable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'verifyPayment'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;callable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="s"&gt;"paymentId"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"12345"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 3: Auto-Update Data (Business Logic)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Use Case:&lt;/strong&gt;&lt;br&gt;
When an order is created → update user stats&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateUserStats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orders/{orderId}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;totalOrders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FieldValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 4: Call External API Securely&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetchWeather&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`https://api.weatherapi.com/v1/current.json?key=API_KEY&amp;amp;q=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 API key stays safe in backend!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices&lt;/strong&gt; ✅&lt;br&gt;
&lt;strong&gt;1. Keep Business Logic in Cloud Functions&lt;/strong&gt;&lt;br&gt;
❌ Don’t trust frontend&lt;br&gt;
✅ Always validate on backend&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Use Environment Config&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase functions:config:set api.key&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_KEY"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Handle Errors Properly&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HttpsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;invalid-argument&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Missing data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Optimize Performance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid heavy loops&lt;/li&gt;
&lt;li&gt;Use async/await properly&lt;/li&gt;
&lt;li&gt;Minimize Firestore reads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Secure Your Functions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use authentication checks:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HttpsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unauthenticated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Common Pitfalls&lt;/strong&gt; ⚠️&lt;br&gt;
❌ &lt;strong&gt;1. Doing Everything in Flutter&lt;/strong&gt;&lt;br&gt;
➡️ Leads to security issues&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;2. Infinite Function Loops&lt;/strong&gt;&lt;br&gt;
Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function writes to Firestore&lt;/li&gt;
&lt;li&gt;Trigger fires again
👉 Fix:
Use flags or conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;3. Large Cold Start Delays&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Happens in unused functions&lt;br&gt;
👉 Fix:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use smaller functions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use regional deployment&lt;br&gt;
❌ &lt;strong&gt;4. Exposing API Keys&lt;/strong&gt;&lt;br&gt;
👉 Always call APIs via Cloud Functions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ &lt;strong&gt;5. Not Handling Errors&lt;/strong&gt;&lt;br&gt;
👉 Always use try/catch&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Pro Tips *&lt;/em&gt;💡&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use TypeScript for better maintainability&lt;/li&gt;
&lt;li&gt;Structure functions into modules&lt;/li&gt;
&lt;li&gt;Log everything using console.log&lt;/li&gt;
&lt;li&gt;Monitor using Firebase Console
&lt;strong&gt;Conclusion&lt;/strong&gt; 🎯
Flutter + Firebase Cloud Functions is a powerful full-stack solution that allows you to build scalable, secure, and modern applications without managing servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 Flutter handles UI beautifully&lt;/li&gt;
&lt;li&gt;🔐 Cloud Functions handle secure backend logic&lt;/li&gt;
&lt;li&gt;⚡ Real-time + serverless = fast &amp;amp; scalable apps&lt;/li&gt;
&lt;li&gt;🧠 Keep sensitive logic off the client&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🔧 Use triggers and callable functions wisely&lt;br&gt;
If you’re building apps with features like:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payments 💳&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Notifications 🔔&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI integrations 🤖&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-time data 📡&lt;br&gt;
👉 Then this stack is one of the best choices available today.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thought&lt;/strong&gt;&lt;br&gt;
Start simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build one function&lt;/li&gt;
&lt;li&gt;Connect it to Flutter&lt;/li&gt;
&lt;li&gt;Expand step by step
And soon, you’ll be building production-ready apps with confidence 🚀&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>serverless</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🚀 How to Create and Use RPC Functions in Supabase with Flutter (Step-by-Step Guide)</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Tue, 12 May 2026 04:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/how-to-create-and-use-rpc-functions-in-supabase-with-flutter-step-by-step-guide-10o0</link>
      <guid>https://dev.to/codexlancers/how-to-create-and-use-rpc-functions-in-supabase-with-flutter-step-by-step-guide-10o0</guid>
      <description>&lt;p&gt;🧠 &lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
When building modern apps, you often need to perform complex database operations — like filtering data, calculating values, or combining multiple queries. Writing all this logic directly in your Flutter app can quickly become messy and inefficient.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;RPC (Remote Procedure Call) functions&lt;/strong&gt; in Supabase come in.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;RPC functions&lt;/strong&gt; allow you to write SQL functions inside your database and call them directly from your app as if they were APIs.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Why use RPC functions in Supabase?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep business logic inside the database (cleaner architecture)&lt;/li&gt;
&lt;li&gt;Reduce network calls (better performance)&lt;/li&gt;
&lt;li&gt;Improve security (controlled access to data)&lt;/li&gt;
&lt;li&gt;Reuse logic across multiple clients (Flutter, Web, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧰 &lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;br&gt;
Before we start, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ A Flutter project set up&lt;/li&gt;
&lt;li&gt;✅ A Supabase project created&lt;/li&gt;
&lt;li&gt;✅ Supabase Flutter SDK installed&lt;/li&gt;
&lt;li&gt;✅ Basic knowledge of SQL (SELECT, WHERE, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚙️ &lt;strong&gt;Step 1: Create an RPC Function in Supabase&lt;/strong&gt;&lt;br&gt;
Let’s say we have a tasks table and we want to fetch all completed tasks for a specific user.&lt;/p&gt;

&lt;p&gt;🗄️ &lt;strong&gt;Example Table:&lt;/strong&gt; tasks&lt;br&gt;
idtitleuser_idis_completed1Task A101true2Task B101false&lt;/p&gt;

&lt;p&gt;🧾 &lt;strong&gt;SQL Function&lt;/strong&gt;&lt;br&gt;
Go to &lt;strong&gt;Supabase Dashboard → SQL Editor&lt;/strong&gt;, and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="k"&gt;replace&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;get_completed_tasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_user_id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;is_completed&lt;/span&gt; &lt;span class="nb"&gt;boolean&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;language&lt;/span&gt; &lt;span class="k"&gt;sql&lt;/span&gt;
&lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_completed&lt;/span&gt;
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;
  &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p_user_id&lt;/span&gt;
    &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;is_completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔍 &lt;strong&gt;Explanation (Simple)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create or replace function → creates the RPC function&lt;/li&gt;
&lt;li&gt;p_user_id → input parameter&lt;/li&gt;
&lt;li&gt;returns table → defines output structure&lt;/li&gt;
&lt;li&gt;select ... → actual query logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧪 &lt;strong&gt;Step 2: Test the Function in Supabase&lt;/strong&gt;&lt;br&gt;
Before using it in Flutter, test it.&lt;/p&gt;

&lt;p&gt;Run this in SQL Editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;get_completed_tasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'your-user-id-here'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Expected Output&lt;/strong&gt;&lt;br&gt;
You should see only completed tasks for that user.&lt;/p&gt;

&lt;p&gt;📱 &lt;strong&gt;Step 3: Call RPC Function in Flutter&lt;/strong&gt;&lt;br&gt;
Now let’s call this function from your Flutter app.&lt;/p&gt;

&lt;p&gt;📦 &lt;strong&gt;Add Supabase Dependency&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;supabase_flutter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latest_version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚡ &lt;strong&gt;Initialize Supabase&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Supabase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;url:&lt;/span&gt; &lt;span class="s"&gt;'YOUR_SUPABASE_URL'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;anonKey:&lt;/span&gt; &lt;span class="s"&gt;'YOUR_SUPABASE_ANON_KEY'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔥 &lt;strong&gt;Call RPC Function&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Supabase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getCompletedTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;supabase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'get_completed_tasks'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;params:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'p_user_id'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🧠 &lt;strong&gt;Explanation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rpc() → calls Supabase function&lt;/li&gt;
&lt;li&gt;'get_completed_tasks' → function name&lt;/li&gt;
&lt;li&gt;params → must match SQL parameter names
🖥️ &lt;strong&gt;Use in UI&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FutureBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;future:&lt;/span&gt; &lt;span class="n"&gt;getCompletedTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CircularProgressIndicator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;itemCount:&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;itemBuilder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ListTile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="nl"&gt;subtitle:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Completed"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🌍 &lt;strong&gt;Real-World Use Case&lt;/strong&gt;&lt;br&gt;
Let’s say you’re building a Task Management App (like your current Flutter project 👀).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqttulxw523qtqd3cpcxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqttulxw523qtqd3cpcxp.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;❌ Fetching all tasks&lt;br&gt;
❌ Filtering in Flutter&lt;/p&gt;

&lt;p&gt;You can:&lt;/p&gt;

&lt;p&gt;✅ Use RPC to fetch only required data&lt;br&gt;
✅ Improve performance and reduce app logic&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Other Use Cases&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calculating total revenue&lt;/li&gt;
&lt;li&gt;Fetching user-specific dashboards&lt;/li&gt;
&lt;li&gt;Complex joins across tables&lt;/li&gt;
&lt;li&gt;Role-based data filtering
⚠️ &lt;strong&gt;Common Mistakes&lt;/strong&gt;
❌ &lt;strong&gt;1. Parameter Name Mismatch&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="nl"&gt;params:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'userId'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// WRONG&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;✔ Must match SQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p_user_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;❌ &lt;strong&gt;2. Forgetting Permissions (RLS)&lt;/strong&gt;&lt;br&gt;
If Row Level Security (RLS) is enabled:&lt;/p&gt;

&lt;p&gt;👉 Make sure policies allow access&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;3. Returning Wrong Data Type&lt;/strong&gt;&lt;br&gt;
If your function returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then handle it properly in Flutter.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;4. Not Testing in SQL First&lt;/strong&gt;&lt;br&gt;
Always test in Supabase before calling from Flutter.&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Best Practices&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Keep functions simple and focused&lt;/strong&gt;&lt;br&gt;
One function = one responsibility&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Use meaningful names&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get_user_tasks ✔
fetch_data ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Secure with RLS policies&lt;/strong&gt;&lt;br&gt;
Don’t expose sensitive data&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Use indexes for performance&lt;/strong&gt;&lt;br&gt;
Especially for large datasets&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Prefer SQL functions over multiple API calls&lt;/strong&gt;&lt;br&gt;
Cleaner + faster&lt;/p&gt;

&lt;p&gt;🏁 &lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
RPC functions in Supabase are a &lt;strong&gt;powerful way to move logic closer to your database&lt;/strong&gt;, making your Flutter apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚡ Faster&lt;/li&gt;
&lt;li&gt;🧹 Cleaner&lt;/li&gt;
&lt;li&gt;🔐 More secure
By following this step-by-step guide, you can now:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✔ Create SQL functions&lt;br&gt;
✔ Test them in Supabase&lt;br&gt;
✔ Call them seamlessly from Flutter&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Next Steps&lt;/strong&gt;&lt;br&gt;
Add &lt;strong&gt;pagination&lt;/strong&gt; to your RPC functions&lt;br&gt;
Use &lt;strong&gt;PostgreSQL joins&lt;/strong&gt; inside functions&lt;br&gt;
Explore &lt;strong&gt;Edge Functions vs RPC&lt;/strong&gt;&lt;br&gt;
Build reusable &lt;strong&gt;backend logic library&lt;/strong&gt;&lt;br&gt;
If you’re building scalable Flutter apps with Supabase, mastering RPC is a &lt;strong&gt;game changer&lt;/strong&gt; 💥&lt;/p&gt;

</description>
      <category>database</category>
      <category>flutter</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🚀 Integrating Tamara Payment Gateway in a FlutterFlow Application</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Mon, 11 May 2026 12:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/integrating-tamara-payment-gateway-in-a-flutterflow-application-4080</link>
      <guid>https://dev.to/codexlancers/integrating-tamara-payment-gateway-in-a-flutterflow-application-4080</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9dhwbmva1zlcoumipqf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm9dhwbmva1zlcoumipqf.png" alt=" " width="720" height="480"&gt;&lt;/a&gt;&lt;br&gt;
In today’s digital ecosystem, integrating a reliable payment gateway is essential for delivering a smooth and secure user experience. However, building a payment system isn’t just about processing transactions — it’s about ensuring &lt;strong&gt;security, reliability, and compliance,&lt;/strong&gt; all while maintaining a seamless user journey.&lt;/p&gt;

&lt;p&gt;Recently, I worked on integrating the &lt;strong&gt;Tamara Payment Gateway&lt;/strong&gt; into a FlutterFlow application, creating a complete end-to-end payment workflow — from initiating transactions to handling real-time updates.&lt;br&gt;
💡 &lt;strong&gt;The Goal&lt;/strong&gt;&lt;br&gt;
The objective was to implement a &lt;strong&gt;secure and scalable payment flow&lt;/strong&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enables users to complete payments smoothly&lt;/li&gt;
&lt;li&gt;Handles transaction states reliably&lt;/li&gt;
&lt;li&gt;Ensures compliance with Tamara’s payment standards&lt;/li&gt;
&lt;li&gt;Works seamlessly across development and production environments
🛠️ &lt;strong&gt;The Implementation&lt;/strong&gt;
The integration involved connecting Tamara’s APIs with the FlutterFlow application and managing the full payment lifecycle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚙️ &lt;strong&gt;Key Features Implemented&lt;/strong&gt;&lt;br&gt;
🔹 &lt;strong&gt;Tamara Checkout API Integration&lt;/strong&gt;&lt;br&gt;
We used Tamara’s Checkout API to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initiate payment sessions&lt;/li&gt;
&lt;li&gt;Redirect users to the hosted checkout page&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Process transactions securely&lt;br&gt;
🔐 &lt;strong&gt;Secure Payment Handling&lt;/strong&gt;&lt;br&gt;
Security was a top priority. The implementation ensured:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proper API request validation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Safe handling of transaction data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compliance with Tamara’s payment flow&lt;br&gt;
🔔 &lt;strong&gt;Webhook Integration for Real-Time Updates&lt;/strong&gt;&lt;br&gt;
To keep track of payment status:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implemented webhooks to receive real-time updates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handled events such as:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payment success&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payment failure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transaction updates&lt;br&gt;
This ensures the app always reflects the correct payment status.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💳 &lt;strong&gt;Payment Method Support&lt;/strong&gt;&lt;br&gt;
Enabled support for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visa cards&lt;/li&gt;
&lt;li&gt;Mada cards
This ensures compatibility with regional payment preferences.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧪 &lt;strong&gt;Environment Configuration&lt;/strong&gt;&lt;br&gt;
Set up both environments:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sandbox (Development)&lt;/strong&gt; for testing&lt;br&gt;
&lt;strong&gt;Production&lt;/strong&gt; for live transactions&lt;br&gt;
This separation ensures safe development and smooth deployment.&lt;/p&gt;

&lt;p&gt;🔄 &lt;strong&gt;Reliable Request &amp;amp; Response Handling&lt;/strong&gt;&lt;br&gt;
Carefully managed API communication to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle success and failure cases&lt;/li&gt;
&lt;li&gt;Prevent duplicate transactions&lt;/li&gt;
&lt;li&gt;Ensure consistency across the payment flow
⚠️ &lt;strong&gt;Key Challenge: Hosted Checkout Limitations&lt;/strong&gt;
One of the most interesting aspects of this integration was understanding the limitations of Tamara’s &lt;strong&gt;hosted checkout flow&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdvbrxz6uiqsf19gugshh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdvbrxz6uiqsf19gugshh.png" alt=" " width="800" height="192"&gt;&lt;/a&gt;&lt;br&gt;
Unlike custom UI payment solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The payment interface is controlled by Tamara&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UI customization options are limited&lt;br&gt;
💡 &lt;strong&gt;Why This Matters&lt;/strong&gt;&lt;br&gt;
At first, this might seem like a limitation, but it actually ensures:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Higher security standards&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Compliance with payment regulations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Reduced risk of implementation errors&lt;br&gt;
Understanding these constraints helped align the integration with best practices recommended by Tamara.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;Final Result&lt;/strong&gt;&lt;br&gt;
The final implementation delivered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A stable and secure payment experience&lt;/li&gt;
&lt;li&gt;Smooth transaction processing&lt;/li&gt;
&lt;li&gt;Accurate real-time payment updates&lt;/li&gt;
&lt;li&gt;Full compliance with Tamara’s standards
Users can now complete payments confidently, knowing the system is both &lt;strong&gt;secure and reliable&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧠 &lt;strong&gt;Key Learnings&lt;/strong&gt;&lt;br&gt;
⚖️ &lt;strong&gt;Balancing UX and Security&lt;/strong&gt;&lt;br&gt;
Not all payment flows allow full UI control. Sometimes, prioritizing security and compliance is more important than customization.&lt;/p&gt;

&lt;p&gt;🔄 &lt;strong&gt;Importance of Webhooks&lt;/strong&gt;&lt;br&gt;
Webhooks are critical for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time updates&lt;/li&gt;
&lt;li&gt;Backend synchronization&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reliable transaction tracking&lt;br&gt;
💻 &lt;strong&gt;Tech Stack&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FlutterFlow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dart&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tamara Payment Gateway APIs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Webhooks for real-time updates&lt;br&gt;
🧠 &lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
This integration reinforced an important lesson:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;A great payment system is not just about UX — it’s about trust, security, and reliability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By combining FlutterFlow with Tamara’s infrastructure, we were able to build a solution that meets both &lt;strong&gt;user expectations and industry standards.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’re working on payment integrations, always remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand platform limitations&lt;/li&gt;
&lt;li&gt;Follow recommended flows&lt;/li&gt;
&lt;li&gt;Prioritize security over customization&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  FlutterFlow #PaymentGateway #Tamara #Fintech #MobileDevelopment #APIIntegration #Webhooks
&lt;/h1&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>nocode</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Google &amp; Apple Sign-In in Flutter</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Mon, 11 May 2026 04:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/google-apple-sign-in-in-flutter-4102</link>
      <guid>https://dev.to/codexlancers/google-apple-sign-in-in-flutter-4102</guid>
      <description>&lt;p&gt;A production-grade walkthrough: clean auth service, real code from a real app, and integration patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Dependencies &amp;amp; Setup&lt;/li&gt;
&lt;li&gt;Getting the Server Client ID&lt;/li&gt;
&lt;li&gt;The Clean AuthService&lt;/li&gt;
&lt;li&gt;Platform Configuration&lt;/li&gt;
&lt;li&gt;Common Errors &amp;amp; Fixes&lt;/li&gt;
&lt;li&gt;UI Example&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  01 / Introduction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why Social Sign-In Still Matters in 2026
&lt;/h3&gt;

&lt;p&gt;Every additional step between a user opening your app and them being inside it is a drop-off point. Password flows are friction. Google and Apple Sign-In are the fastest path from “curious” to “engaged” — two taps and you’re in, no new password to forget.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Who this is for&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Flutter developers at any level who want latest Google and Apple Sign-In that actually works in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  02 / Prerequisites
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What You Need Before Starting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A Firebase project with Authentication enabled — Google and Apple providers turned on&lt;/li&gt;
&lt;li&gt;FlutterFire CLI installed and flutterfire configure already run&lt;/li&gt;
&lt;li&gt;For Apple Sign-In: an Apple Developer account with Sign In with Apple capability enabled&lt;/li&gt;
&lt;li&gt;For Android Google Sign-In: SHA-1 fingerprint registered in Firebase Console&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  03 / Dependencies &amp;amp; Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Packages, pubspec, and Initialization
&lt;/h3&gt;

&lt;p&gt;Add to pubspec.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;flutter_dotenv&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^5.2.1&lt;/span&gt;
  &lt;span class="na"&gt;firebase_core&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^3.10.1&lt;/span&gt;
  &lt;span class="na"&gt;firebase_auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^5.5.1&lt;/span&gt;
  &lt;span class="na"&gt;google_sign_in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^7.2.0&lt;/span&gt;
  &lt;span class="na"&gt;sign_in_with_apple&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^7.0.1&lt;/span&gt;

&lt;span class="na"&gt;flutter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;assets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter pub get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Create your .env file
&lt;/h3&gt;

&lt;p&gt;Store sensitive config outside of source code. Create a .env file in your project root and add it to .gitignore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Get this from Google Cloud Console → OAuth 2.0 → Web Client (see Section 4)
SERVER_CLIENT_ID=123456789-abcdefg.apps.googleusercontent.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Initialize Firebase and Google Sign-In in main.dart
&lt;/h3&gt;

&lt;p&gt;This is the most important step people miss, you must call GoogleSignIn.instance.initialize() before runApp(), after Firebase is ready:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter_dotenv/flutter_dotenv.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:firebase_core/firebase_core.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:your_app/service/auth_service.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;WidgetsFlutterBinding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ensureInitialized&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. Load environment variables&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;fileName:&lt;/span&gt; &lt;span class="s"&gt;'.env'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. Initialize Firebase&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Firebase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;options:&lt;/span&gt; &lt;span class="n"&gt;DefaultFirebaseOptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentPlatform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 3. Initialize AuthService (which calls GoogleSignIn.instance.initialize)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="n"&gt;runApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🚨 Skip initialize() and you’ll get a StateError&lt;/p&gt;

&lt;p&gt;If you call authenticate() or authorizationClient before initialize(), Flutter throws a StateError: instance not initialized. This crashes silently in release builds. Always initialize first.&lt;/p&gt;




&lt;h2&gt;
  
  
  04 / Google Cloud Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Getting the Server Client ID (Web OAuth Client)
&lt;/h3&gt;

&lt;p&gt;The serverClientId is the Web Client ID from Google Cloud Console — not the Android or iOS client. It is required for Google Sign-In on Android and enables server-side token verification. Here's exactly how to find it:&lt;/p&gt;

&lt;h3&gt;
  
  
  Google Cloud Console — Step-by-step walkthrough
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://console.cloud.google.com/" rel="noopener noreferrer"&gt;console.cloud.google.com&lt;/a&gt; and select your Firebase project (same project name as in Firebase Console)&lt;/p&gt;

&lt;p&gt;2 . In the left sidebar, navigate to &lt;a href="https://console.cloud.google.com/apis/credentials" rel="noopener noreferrer"&gt;APIs &amp;amp; Services → Credentials&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Under OAuth 2.0 Client IDs, look for the entry with type “Web application”. It is usually auto-created by Firebase and named something like “Web client (auto created by Google Service)”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the Web application entry to open its details&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the Client ID field — it ends in .apps.googleusercontent.com. This is your SERVER_CLIENT_ID.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste it into your .env file as SERVER_CLIENT_ID=your_id&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;💡 Can’t find the Web Client?&lt;/p&gt;

&lt;p&gt;If you don’t see a Web Client ID, go to Firebase Console → Authentication → Sign-in method → Google → click the expand arrow. Firebase will show you the Web SDK configuration which contains the same client ID.&lt;/p&gt;

&lt;p&gt;⚠️ Android vs iOS vs Web — use the Web client&lt;/p&gt;

&lt;p&gt;There will be separate entries for Android, iOS, and Web in the credentials list. The serverClientId parameterspecifically requires the Web client ID. Using the Android or iOS client ID here is a common mistake that silently fails.&lt;/p&gt;




&lt;h2&gt;
  
  
  05 / The Clean AuthService
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Authentication Service Implementation
&lt;/h3&gt;

&lt;p&gt;Here’s the authentication logic, cleaned up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;lib/service/auth_service.dart&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:developer'&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'dart:math'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:firebase_auth/firebase_auth.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter_dotenv/flutter_dotenv.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:google_sign_in/google_sign_in.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:sign_in_with_apple/sign_in_with_apple.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;/// Clean authentication service — auth logic only, no database concerns.&lt;/span&gt;
&lt;span class="c1"&gt;/// Use it as a foundation and add your own data layer on top.&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ─── Singleton ───────────────────────────────────────────&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;AuthService&lt;/span&gt; &lt;span class="n"&gt;_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AuthService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_internal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;factory&lt;/span&gt; &lt;span class="n"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;AuthService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;_internal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// ─── Firebase + Google ────────────────────────────────────&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;FirebaseAuth&lt;/span&gt; &lt;span class="n"&gt;_auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FirebaseAuth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;GoogleSignIn&lt;/span&gt; &lt;span class="n"&gt;_googleSignIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GoogleSignIn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;/// Web Client ID from Google Cloud Console → OAuth 2.0 → Web application&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;_serverClientId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'SERVER_CLIENT_ID'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// ─── Public Getters ───────────────────────────────────────&lt;/span&gt;
  &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;currentUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;isSignedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;currentUser&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// ─── Initialization ───────────────────────────────────────&lt;/span&gt;

  &lt;span class="c1"&gt;/// Call once at app startup, after Firebase.initializeApp().&lt;/span&gt;
  &lt;span class="c1"&gt;/// Required by google_sign_in v7+ before any sign-in call.&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_googleSignIn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;serverClientId:&lt;/span&gt; &lt;span class="n"&gt;_serverClientId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'[AuthService] Google Sign-In initialized'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'[AuthService] Google init error: &lt;/span&gt;&lt;span class="si"&gt;$e&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;rethrow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// fail fast — misconfiguration should be caught at startup&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ─── Google Sign-In ───────────────────────────────────────&lt;/span&gt;

  &lt;span class="c1"&gt;/// Signs in with Google and returns a Firebase [UserCredential].&lt;/span&gt;
  &lt;span class="c1"&gt;/// Throws on cancellation or error — catch in your controller/notifier.&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UserCredential&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;signInWithGoogle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Sign out first — ensures the account picker is always shown&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_googleSignIn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// 1. Trigger Google authentication — shows the account picker&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;GoogleSignInAccount&lt;/span&gt; &lt;span class="n"&gt;googleUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_googleSignIn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;scopeHint:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Get the ID token directly from the authenticated account&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;GoogleSignInAuthentication&lt;/span&gt; &lt;span class="n"&gt;googleAuth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;googleUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authentication&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Also get the access token from the authorization client (for scopes)&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;authClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_googleSignIn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authorizationClient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;authorization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;authClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authorizationForScopes&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'profile'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Build the Firebase credential from both tokens&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GoogleAuthProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;idToken:&lt;/span&gt; &lt;span class="n"&gt;googleAuth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;idToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;accessToken:&lt;/span&gt; &lt;span class="n"&gt;authorization&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 5. Sign into Firebase — creates the user on first login automatically&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;signInWithCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ─── Apple Sign-In ────────────────────────────────────────&lt;/span&gt;

  &lt;span class="c1"&gt;/// Signs in with Apple ID and returns a Firebase [UserCredential].&lt;/span&gt;
  &lt;span class="c1"&gt;/// Throws on cancellation or error — catch in your controller/notifier.&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UserCredential&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;signInWithApple&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Generate a cryptographically random nonce (replay-attack protection)&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;rawNonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_generateNonce&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Request Apple credential — opens the system Sign-In sheet&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;appleCredential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;SignInWithApple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAppleIDCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;scopes:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;AppleIDAuthorizationScopes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;AppleIDAuthorizationScopes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Build the Firebase OAuthCredential using Apple's identity token&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;oAuthCredential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OAuthProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'apple.com'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;idToken:&lt;/span&gt; &lt;span class="n"&gt;appleCredential&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;identityToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;rawNonce:&lt;/span&gt; &lt;span class="n"&gt;rawNonce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;accessToken:&lt;/span&gt; &lt;span class="n"&gt;appleCredential&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authorizationCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. Sign into Firebase&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;signInWithCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oAuthCredential&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ─── Sign Out ─────────────────────────────────────────────&lt;/span&gt;

  &lt;span class="c1"&gt;/// Signs out from both Firebase and Google simultaneously.&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="n"&gt;_auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="n"&gt;_googleSignIn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ─── Error Messages ───────────────────────────────────────&lt;/span&gt;

  &lt;span class="c1"&gt;/// Converts a FirebaseAuthException into a user-readable message.&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;getFirebaseErrorMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FirebaseAuthException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'user-not-found'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'No account found with this email.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'wrong-password'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'Incorrect password.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'email-already-in-use'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'This email is already registered.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'invalid-email'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'Please enter a valid email.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'weak-password'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'Password is too weak.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'too-many-requests'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'Too many attempts. Try again later.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'network-request-failed'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'No internet connection.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'operation-not-allowed'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'This sign-in method is not enabled.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;'account-exists-with-different-credential'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'An account with this email exists with a different sign-in method.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;'Authentication failed. Please try again.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ─── Nonce Generator (Apple Sign-In) ─────────────────────&lt;/span&gt;

  &lt;span class="c1"&gt;/// Generates a cryptographically secure random string.&lt;/span&gt;
  &lt;span class="c1"&gt;/// Apple uses this to prevent replay attacks on the identity token.&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;_generateNonce&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;charset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;charset&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nextInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  06 / Platform Configuration
&lt;/h2&gt;

&lt;p&gt;Android &amp;amp; iOS Setup&lt;/p&gt;

&lt;h3&gt;
  
  
  Android — Google Sign-In
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Get your SHA-1 fingerprint
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Debug keystore (development)&lt;/span&gt;
keytool &lt;span class="nt"&gt;-list&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-keystore&lt;/span&gt; ~/.android/debug.keystore &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-alias&lt;/span&gt; androiddebugkey &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-storepass&lt;/span&gt; android &lt;span class="nt"&gt;-keypass&lt;/span&gt; android
&lt;span class="c"&gt;# Copy the SHA1 line from the output, e.g.:&lt;/span&gt;
&lt;span class="c"&gt;# SHA1: A1:B2:C3:D4:E5:F6:...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this SHA-1 in Firebase Console → Project Settings → Your Android app → Add fingerprint. Then re-download google-services.json and place it at android/app/google-services.json.&lt;/p&gt;

&lt;p&gt;Become a Medium member&lt;/p&gt;

&lt;p&gt;⚠️ Add both debug and release SHA-1&lt;/p&gt;

&lt;p&gt;The debug SHA-1 works only during development. For production (Play Store), add the SHA-1 from yourupload keystore. Missing the release SHA-1 causes silent failures after publishing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify build.gradle files&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;android/build.gradle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="k"&gt;buildscript&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;classpath&lt;/span&gt; &lt;span class="s1"&gt;'com.google.gms:google-services:4.4.2'&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;android/app/build.gradle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Must be at the very bottom of the file&lt;/span&gt;
&lt;span class="n"&gt;apply&lt;/span&gt; &lt;span class="nl"&gt;plugin:&lt;/span&gt; &lt;span class="s1"&gt;'com.google.gms.google-services'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  iOS — Google Sign-In
&lt;/h3&gt;

&lt;p&gt;Add the reversed client ID URL scheme&lt;/p&gt;

&lt;p&gt;Open GoogleService-Info.plist, find the REVERSED_CLIENT_ID value, then add it to ios/Runner/Info.plist:&lt;/p&gt;

&lt;p&gt;ios/Runner/Info.plist&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleURLTypes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleTypeRole&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Editor&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;CFBundleURLSchemes&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- REVERSED_CLIENT_ID from GoogleService-Info.plist --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.googleusercontent.apps.YOUR_REVERSED_CLIENT_ID&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  iOS — Apple Sign-In
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Enable the capability in Xcode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open ios/Runner.xcworkspace in Xcode → select Runner target → Signing &amp;amp; Capabilities → + Capability → Sign In with Apple.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable in Apple Developer Portal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Log into developer.apple.com → Identifiers → select your App ID → check Sign In with Apple → Save. Regenerate your provisioning profile.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable in Firebase Console&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Firebase Console → Authentication → Sign-in method → Apple → Enable. Paste your App ID (e.g. com.company.app) as the Service ID.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the entitlement (if needed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Xcode usually handles this automatically when you add the capability. Verify Runner.entitlements contains com.apple.developer.applesignin with value Default.&lt;/p&gt;

&lt;p&gt;💡 Apple Sign-In on Android&lt;/p&gt;

&lt;p&gt;sign_in_with_apple supports Android via a web-based OAuth flow. You need to configure a web redirect URL in Apple Developer Console and add it to the plugin configuration. See the package README for the full Android setup guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  07 / Debugging
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common Errors &amp;amp; Exact Fixes
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;StateError: instance not initialized&lt;br&gt;
Root Cause: GoogleSignIn.instance is used before calling initialize()&lt;br&gt;
Fix: Make sure to call and await AuthService().initialize() inside main() before runApp()&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sign_in_failed (Android)&lt;br&gt;
Root Cause: SHA-1 fingerprint is missing or incorrect&lt;br&gt;
Fix: Add both debug and release SHA-1 in Firebase Console, then re-download google-services.json&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PlatformException: sign_in_canceled&lt;br&gt;
Root Cause: User closed the Google account picker&lt;br&gt;
Fix: This is expected behavior — handle it silently without showing an error toast&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;operation-not-allowed&lt;br&gt;
Root Cause: Google Sign-In is not enabled in Firebase&lt;br&gt;
Fix: Go to Firebase Console → Authentication → Sign-in method → Enable Google&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;idToken is null&lt;br&gt;
Root Cause: Authentication failed or was canceled silently&lt;br&gt;
Fix: Always check googleAuth.idToken != null before creating credentials&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Missing REVERSED_CLIENT_ID (iOS)&lt;br&gt;
Root Cause: URL scheme is not configured in Info.plist&lt;br&gt;
Fix: Add CFBundleURLSchemes using the REVERSED_CLIENT_ID from GoogleService-Info.plist&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AuthorizationError: canceled (Apple)&lt;br&gt;
Root Cause: User canceled Apple Sign-In&lt;br&gt;
Fix: Catch SignInWithAppleAuthorizationException and ignore when e.code == AuthorizationErrorCode.canceled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apple name is null (returning user)&lt;br&gt;
Root Cause: Apple only provides the user’s name during the first sign-in&lt;br&gt;
Fix: Save the name in your database when isNewUser == true and reuse it later&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;account-exists-with-different-credential&lt;br&gt;
Root Cause: Same email is used with another authentication provider&lt;br&gt;
Fix: Use fetchSignInMethodsForEmail() and guide the user to link accounts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apple Sign-In not working on Simulator&lt;br&gt;
Root Cause: iOS Simulator does not support Apple Sign-In&lt;br&gt;
Fix: Always test Apple Sign-In on a real device&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  08 / UI Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// GOOGLE LOGIN&lt;/span&gt;
&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loginWithGoogle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;signInWithGoogle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_showMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Google Login Success ✅"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_showMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s"&gt;"Error"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;/// APPLE LOGIN&lt;/span&gt;
&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loginWithApple&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;signInWithApple&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_showMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Apple Login Success 🍎"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_showMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s"&gt;"Error"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  09 / Conclusion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Summary &amp;amp; Best Practices
&lt;/h3&gt;

&lt;p&gt;Here’s the complete checklist for production-ready social sign-in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initialize once — call AuthService().initialize() in main() after Firebase and before runApp()&lt;/li&gt;
&lt;li&gt;Server Client ID = Web Client — get the Web application client from Google Cloud Console, not Android or iOS&lt;/li&gt;
&lt;li&gt;Sign out Google on each sign-in — call _googleSignIn.signOut() before authenticating so the picker always appears&lt;/li&gt;
&lt;li&gt;Both tokens for Firebase — always pass both idToken and accessToken to GoogleAuthProvider.credential()&lt;/li&gt;
&lt;li&gt;Use a secure nonce for Apple — generate it with Random.secure(), always pass rawNonce to the Firebase credential&lt;/li&gt;
&lt;li&gt;Save Apple name immediately — it’s only available on the first sign-in; save it to your database right after isNewUser == true&lt;/li&gt;
&lt;li&gt;Detect new vs returning users — use userCredential.additionalUserInfo?.isNewUser to branch your post-auth flow&lt;/li&gt;
&lt;li&gt;Sign out from both — always call both _auth.signOut() and _googleSignIn.signOut() on logout&lt;/li&gt;
&lt;li&gt;SHA-1: debug + release — add both fingerprints to Firebase or Google Sign-In breaks in production builds&lt;/li&gt;
&lt;li&gt;Test Apple on a real device — iOS Simulator does not support Apple Sign-In.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>flutter</category>
      <category>mobile</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🚀 FlutterFlow’s New Feature: App Events (A Game Changer for Scalable Apps)</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Sat, 09 May 2026 04:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/flutterflows-new-feature-app-events-a-game-changer-for-scalable-apps-1hp9</link>
      <guid>https://dev.to/codexlancers/flutterflows-new-feature-app-events-a-game-changer-for-scalable-apps-1hp9</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F124qkagvo1woq4xk9r3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F124qkagvo1woq4xk9r3s.png" alt=" " width="720" height="480"&gt;&lt;/a&gt;&lt;br&gt;
Building scalable applications in low-code platforms has always been a balance between &lt;strong&gt;speed and maintainability&lt;/strong&gt;. While FlutterFlow makes UI development incredibly fast, managing communication between different parts of an app could sometimes become complex.&lt;/p&gt;

&lt;p&gt;But with the introduction of &lt;strong&gt;App Events&lt;/strong&gt;, FlutterFlow has taken a major step forward — bringing cleaner architecture, better performance, and a much more scalable approach to app development.&lt;/p&gt;

&lt;p&gt;🤯 &lt;strong&gt;The Problem Before App Events&lt;/strong&gt;&lt;br&gt;
Before this update, handling communication between screens or components often involved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Passing multiple navigation parameters&lt;/li&gt;
&lt;li&gt;❌ Managing complex global or local state&lt;/li&gt;
&lt;li&gt;&lt;p&gt;❌ Writing tightly coupled logic between screens&lt;br&gt;
As apps grew larger, this approach became:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hard to maintain&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Difficult to debug&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Less scalable&lt;br&gt;
💡 &lt;strong&gt;What Are App Events?&lt;/strong&gt;&lt;br&gt;
App Events introduce a &lt;strong&gt;decoupled communication system&lt;/strong&gt; inside FlutterFlow.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Core Idea:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trigger an event from anywhere in the app&lt;/li&gt;
&lt;li&gt;Listen and respond to that event from anywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No direct connection between components is required.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsh420jn9ihkyrzfv1h3c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsh420jn9ihkyrzfv1h3c.png" alt=" " width="800" height="192"&gt;&lt;/a&gt;&lt;br&gt;
This means your app becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More modular&lt;/li&gt;
&lt;li&gt;Easier to maintain&lt;/li&gt;
&lt;li&gt;Much cleaner in terms of logic
🔄 &lt;strong&gt;How It Works (Simple Example)&lt;/strong&gt;
Let’s say a user adds an item to the cart 🛒&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Without App Events:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manually update cart badge&lt;/li&gt;
&lt;li&gt;Refresh product list&lt;/li&gt;
&lt;li&gt;Update summary screen&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass state across multiple screens&lt;br&gt;
&lt;strong&gt;With App Events:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trigger event → “Cart Updated”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All relevant UI components automatically react&lt;br&gt;
✨ That’s it. No messy logic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔑 &lt;strong&gt;Key Highlights&lt;/strong&gt;&lt;br&gt;
🌍 &lt;strong&gt;Global Events&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App-level events&lt;/li&gt;
&lt;li&gt;Handled across the entire application&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Processed sequentially&lt;br&gt;
&lt;strong&gt;Perfect for&lt;/strong&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication state changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Analytics tracking&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logging&lt;br&gt;
📍 &lt;strong&gt;Local Events&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scoped to specific pages or components&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support multiple listeners&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trigger instant UI updates&lt;br&gt;
&lt;strong&gt;Perfect for:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UI refresh&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Component communication&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dynamic interactions&lt;br&gt;
🚀 &lt;strong&gt;Why This Feature Matters&lt;/strong&gt;&lt;br&gt;
App Events bring FlutterFlow closer to &lt;strong&gt;modern software architecture&lt;/strong&gt; patterns, such as:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event-driven systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Loose coupling&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reactive UI updates&lt;br&gt;
💥 &lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Less complex code structure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Better performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easier debugging&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved scalability&lt;br&gt;
⚡ &lt;strong&gt;My Take&lt;/strong&gt;&lt;br&gt;
This is easily one of the &lt;strong&gt;most impactful updates in FlutterFlow&lt;/strong&gt; in recent times.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It solves a real problem developers face when scaling apps and introduces a pattern that aligns with how modern applications are built.&lt;/p&gt;

&lt;p&gt;🧩 &lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
FlutterFlow continues to evolve beyond just a UI builder — it’s becoming a &lt;strong&gt;serious development platform&lt;/strong&gt; capable of handling complex applications.&lt;/p&gt;

&lt;p&gt;App Events are a big step in that direction.&lt;/p&gt;

&lt;p&gt;👉 If you haven’t explored it yet, now is the time.&lt;/p&gt;

&lt;h1&gt;
  
  
  FlutterFlow #NoCode #LowCode #AppDevelopment #MobileDevelopment #Firebase #UIUX #TechUpdate #Developers
&lt;/h1&gt;

</description>
      <category>architecture</category>
      <category>flutter</category>
      <category>news</category>
      <category>nocode</category>
    </item>
    <item>
      <title>🚀 1. How I Built a Production-Ready AI Chat App in FlutterFlow (With OpenAI + Firebase)</title>
      <dc:creator>Codexlancers</dc:creator>
      <pubDate>Fri, 08 May 2026 04:30:00 +0000</pubDate>
      <link>https://dev.to/codexlancers/1-how-i-built-a-production-ready-ai-chat-app-in-flutterflow-with-openai-firebase-lem</link>
      <guid>https://dev.to/codexlancers/1-how-i-built-a-production-ready-ai-chat-app-in-flutterflow-with-openai-firebase-lem</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7bwa41yb56cm4bpks86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7bwa41yb56cm4bpks86.png" alt=" "&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
AI is everywhere in 2026 — but building a production-ready AI chat app is still challenging, especially when using low-code tools like FlutterFlow.&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk you through how I built a scalable AI chat system using &lt;strong&gt;FlutterFlow + Firebase + OpenAI API.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Architecture Overview&lt;/strong&gt;&lt;br&gt;
My setup looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt; → FlutterFlow UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt; → Firebase (Firestore + Cloud Functions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Engine&lt;/strong&gt; → OpenAI API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage&lt;/strong&gt; → Chat history in Firestore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💬** Chat Data Structure**&lt;br&gt;
Each message is stored like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello AI"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hi, how can I help?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server_time"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 This allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy chat history retrieval&lt;/li&gt;
&lt;li&gt;Real-time UI updates&lt;/li&gt;
&lt;li&gt;Scalable structure
🔐 &lt;strong&gt;Securing OpenAI API&lt;/strong&gt;
Never expose your API key in the frontend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyh2uoi2iuq6qcqc1j2wl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyh2uoi2iuq6qcqc1j2wl.png" alt=" "&gt;&lt;/a&gt;&lt;br&gt;
Instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;Firebase Cloud Functions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Send request → backend → OpenAI → return response
This keeps your app secure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚡ &lt;strong&gt;Handling Token Usage (Cost Control)&lt;/strong&gt;&lt;br&gt;
AI APIs can get expensive.&lt;/p&gt;

&lt;p&gt;What I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limit message length&lt;/li&gt;
&lt;li&gt;Store token usage&lt;/li&gt;
&lt;li&gt;Restrict free users (daily limit)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🎯 &lt;strong&gt;UI Challenges &amp;amp; Solutions&lt;/strong&gt;&lt;br&gt;
Problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Chat UI lag with many messages&lt;br&gt;
Solution:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pagination&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lazy loading&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Efficient Firestore queries&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀 &lt;strong&gt;Final Result&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time AI chat&lt;/li&gt;
&lt;li&gt;Scalable backend&lt;/li&gt;
&lt;li&gt;Controlled cost&lt;/li&gt;
&lt;li&gt;Smooth UI
💡 &lt;strong&gt;Final Thoughts&lt;/strong&gt;
FlutterFlow is powerful — but combining it with backend logic is the real game-changer.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>flutter</category>
      <category>nocode</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
