> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-llms-scoped-indexes.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Best Practices

> Recommended patterns and practices for building with the CometChat Flutter SDK.

Follow these best practices to build reliable, performant, and secure applications with the CometChat Flutter SDK. Organized by topic — jump to what's relevant for your current work.

## Initialization & Authentication

| Practice | Description |
| - | - |
| Initialize once at startup | Call `CometChat.init()` in your `main()` or root widget's `initState()`. It only needs to be called once per session. |
| Use environment variables | Store App ID, Region, and Auth Key in a config file or environment variables rather than hardcoding them. |
| Check for existing sessions | Before calling `login()`, use `CometChat.getLoggedInUser()` to check if a session already exists. |
| Use Auth Tokens in production | Auth Keys are for development only. Generate Auth Tokens server-side using the [REST API](https://api-explorer.cometchat.com/reference/create-authtoken). |
| Handle token expiry | Implement a mechanism to detect login failures due to expired tokens. Use the [Login Listener](/sdk/flutter/authentication-overview#login-listener) to detect session changes. |
| Logout on sign-out | Always call `CometChat.logout()` when your user signs out to clear the SDK session and stop real-time events. |

## Listeners

| Practice | Description |
| - | - |
| Use unique listener IDs | Use descriptive IDs like `"MESSAGE_LISTENER_CHAT_SCREEN"` to avoid accidental overwrites. |
| Register early, remove on cleanup | Register listeners after `login()`. Remove them in your widget's `dispose()` method to prevent memory leaks. |
| Keep callbacks lightweight | Avoid heavy processing inside listener callbacks. Use `setState()` or dispatch events to your state management layer. |
| Use specific listeners | Only register the listener types you need. Don't register a `GroupListener` if your page only handles messages. |

## Pagination & Caching

| Practice | Description |
| - | - |
| Use reasonable limits | Set `setLimit()` to 30–50 for users, messages, and group members. |
| Reuse request objects | Call `fetchNext()`/`fetchPrevious()` on the same request instance. Creating a new object resets the cursor. |
| Cache frequently accessed data | Store user and group objects locally to reduce API calls. |

## Rate Limits

| Practice | Description |
| - | - |
| Batch operations | Space out bulk operations using a queue or throttle mechanism. |
| Distinguish operation types | Core operations (login, create/delete user) share a 10,000/min limit. Standard operations have 20,000/min. Avoid frequent login/logout cycles. |

## Messaging

| Practice | Description |
| - | - |
| Use appropriate message types | Choose text, media, or custom messages based on your content. |
| Add metadata for context | Use `metadata` to attach location, device info, or other contextual data to messages. |
| Handle errors gracefully | Always implement `onError` callbacks to handle network issues or invalid parameters. |
| Validate file types | Before sending media messages, verify the file type matches the message type. |
| Hide deleted/blocked content | Use `hideDeletedMessages(true)` and `hideMessagesFromBlockedUsers(true)` on your `MessagesRequestBuilder` for cleaner lists. |

## Threaded Messages

| Practice | Description |
| - | - |
| Track active thread ID | Store the current thread's `parentMessageId` to filter incoming messages. |
| Use hideReplies(true) | Exclude thread replies from main conversation to avoid clutter. |
| Show reply count | Display the number of replies on parent messages to indicate thread activity. |

## Reactions & Mentions

| Practice | Description |
| - | - |
| Update UI optimistically | Show reactions immediately, then sync with server response. |
| Use correct mention format | Always use `<@uid:UID>` format for mentions in message text. |
| Highlight mentions in UI | Parse message text and style mentions differently using Flutter's `RichText` or `Text.rich`. |

## Typing Indicators

| Practice | Description |
| - | - |
| Debounce typing events | Don't call `startTyping()` on every keystroke — debounce to \~300ms intervals. |
| Auto-stop typing | Call `endTyping()` after 3–5 seconds of inactivity or when the user sends a message. |

## Delivery & Read Receipts

| Practice | Description |
| - | - |
| Mark as delivered on fetch | Call `markAsDelivered()` when messages are fetched and displayed. |
| Mark as read on view | Call `markAsRead()` when the user actually views/scrolls to a message. |
| Batch receipts | Mark the last message in a batch — all previous messages are automatically marked. |

## Groups

| Practice | Description |
| - | - |
| Use meaningful GUIDs | Choose descriptive, unique GUIDs (e.g., `"project-alpha-team"`). |
| Set group type carefully | Group type cannot be changed after creation. Choose between `public`, `password`, and `private`. |
| Add members at creation | Use `createGroupWithMembers()` to add initial members in a single API call. |
| Check hasJoined before joining | Avoid unnecessary API calls by checking the group's `hasJoined` property first. |
| Transfer ownership before leaving | Owners must transfer ownership to another member before they can leave. |
| Use joinedOnly(true) | Filter to joined groups when building sidebars or group lists. |

## Group Members

| Practice | Description |
| - | - |
| Batch member additions | Add multiple members in a single `addMembersToGroup()` call. |
| Set appropriate scopes | Assign `participant` by default. Only use `admin` or `moderator` when needed. |
| Handle partial failures | Check each entry in the response map for success or error messages. |
| Kick vs. Ban | Use kick when the user can rejoin. Use ban for permanent removal until unbanned. |

## Calling

| Practice | Description |
| - | - |
| Initialize Calls SDK after Chat SDK | Always initialize Chat SDK (`CometChat.init()`) before Calls SDK (`CometChatCalls.init()`). |
| Store session ID immediately | Save the session ID from `initiateCall()` response — you'll need it for accept, reject, cancel. |
| Handle all call states | Implement handlers for all listener events (accepted, rejected, cancelled, busy, ended). |
| Generate tokens just-in-time | Generate call tokens immediately before starting a session rather than caching them. |
| Clean up on session end | Always call `CometChatCalls.endSession()` in both `onCallEnded` and `onCallEndButtonPressed` callbacks. |
| Inform users about recording | Always notify participants when recording starts — this is often a legal requirement. |
| Limit presenters to 5 | Additional users should join as viewers. |

## Connection & WebSocket

| Practice | Description |
| - | - |
| Register connection listener early | Add the listener right after `CometChat.init()` succeeds. |
| Show connection status in UI | Display a banner when disconnected so users know messages may be delayed. |
| Queue actions during disconnection | Queue user actions and retry once `onConnected` fires. |
| Don't poll getConnectionStatus() | Use the listener-based approach instead. |
| Reconnect on app foreground | If you disconnect in background, call `CometChat.connect()` when returning to foreground. |

## Flutter-Specific Practices

| Practice | Description |
| - | - |
| iOS Podfile configuration | Run `pod install` in the `ios/` directory after adding the SDK dependency. Set the minimum iOS deployment target as required. |
| Android minimum API level | Ensure `minSdkVersion` in `android/app/build.gradle` meets the SDK requirement. |
| Use `dispose()` for cleanup | Always remove listeners and cancel subscriptions in your widget's `dispose()` method. |
| Use `debugPrint` for logging | Prefer `debugPrint()` over `print()` for SDK-related logging — it handles long strings and is stripped in release builds. |
| Handle platform exceptions | CometChat methods may throw `PlatformException` from native channels. Wrap calls in try/catch blocks. |
| State management integration | Dispatch SDK events to your state management layer (Provider, Bloc, Riverpod) rather than calling `setState()` directly in listener callbacks. |

## Upgrading from V3

| Practice | Description |
| - | - |
| Follow the setup guide first | Complete the v4 [setup instructions](/sdk/flutter/setup) before changing dependencies. |
| Update pubspec.yaml | Replace the v3 `cometchat_pro` dependency with the v4 `cometchat_sdk` package. |
| Test incrementally | Test each feature area (messaging, calling, groups) individually after updating. |
| Remove old packages | Remove v3 packages from `pubspec.yaml` and run `flutter pub get` to avoid conflicts. |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Troubleshooting" icon="wrench" href="/sdk/flutter/v4/troubleshooting">
    Common issues and solutions
  </Card>

  <Card title="Setup SDK" icon="gear" href="/sdk/flutter/setup">
    Installation and initialization guide
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.