> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-angular-v5-docs-update.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/troubleshooting">
    Common issues and solutions
  </Card>

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