Skip to main content

Chat Module

Quick Answer

The chat module lives in src/core/chat. It provides conversation lists, one-to-one chat, group chat, messages, reactions, media messages, typing state, and backend hooks.

For Firebase-backed apps, chat uses a mix of Firestore listeners and Firebase callable Functions. That means local UI can render without a custom server, but production chat still needs Firebase Functions deployed and Firestore rules configured.

Source Map

src/core/chat
├── IMChat
├── IMChatScreen
├── IMConversationList
├── IMConversationListView
├── IMConversationView
├── api
├── assets
├── config.ts
└── index.ts

Important exports:

ExportPurpose
IMChatScreenFull chat room screen for one-to-one and group conversations.
IMConversationListViewConversation list UI for the current user.
IMConversationIconViewAvatar/group icon display for conversations.
IMCreateGroupScreenGroup chat creation flow when the group chat flag is enabled.
useChatChannelsHook for the user's conversation list.
useChatMessagesHook for messages in one channel.
useChatSingleChannelHook for a single channel document.
useChatChannelsAndFriendsCombined chat and friend data when social graph is enabled.

Backend Providers

The active chat backend is selected in:

src/core/chat/api/index.ts

Current provider options may include:

ProviderPathUse case
Firebasesrc/core/chat/api/firebaseDefault production path for Firebase apps.
AWSsrc/core/chat/api/awsAWS-backed app variants.
Backendsrc/core/chat/api/backendCustom server implementation.
Localsrc/core/chat/api/localDemo/local data implementation.

Do not mix providers inside one app unless you intentionally migrate the full chat data layer.

Open A Chat Screen

Use the channel object expected by the app navigation flow. A one-to-one channel usually uses a deterministic ID made from the two user IDs.

const firstUserID = currentUser.id
const secondUserID = otherUser.id
const channelID =
firstUserID < secondUserID
? firstUserID + secondUserID
: secondUserID + firstUserID

navigation.navigate('ChatScreen', {
channel: {
id: channelID,
channelID,
participants: [currentUser, otherUser],
},
})

Prefer using the existing app screens and managers to create channels. They already handle group metadata, participant shape, and backend calls.

Firebase Requirements

For Firebase chat, verify:

  • Firebase Auth is enabled.
  • Firestore is enabled.
  • Firebase Functions are deployed for channel and message operations.
  • Firestore rules restrict channel/message reads to participants.
  • Composite indexes exist for the queries used by conversation and message lists.
  • Push notifications are configured if the app sends message notifications.
  • Storage or media upload Functions are configured if chat supports media messages.

The Firebase chat client intentionally returns empty arrays on listener errors to avoid infinite loading. If a conversation list is blank, check logs and Firebase rules before changing UI state.

Media Messages

Media messages usually flow through:

src/core/camera
src/core/media
src/core/chat

A chat screen should handle these failure states separately:

  • permission denied;
  • image/video picker canceled;
  • upload failed;
  • message insert failed after upload;
  • channel listener permission denied.

Switching To A Custom Backend

To replace Firebase chat with your own backend:

  1. Keep the UI exports from src/core/chat.
  2. Implement the same hook contracts in src/core/chat/api/backend.
  3. Switch exports in src/core/chat/api/index.ts.
  4. Make sure the new backend supports list channels, subscribe/fetch messages, create channel, send message, reactions, group updates, and delete/leave behavior.
  5. Re-test one-to-one chat, group chat, media messages, and blocked-user filtering.

Verification Checklist

Test:

  • empty conversation list resolves without infinite loading;
  • existing conversations load;
  • one-to-one chat opens;
  • group chat opens if enabled;
  • text message sends;
  • media message sends if enabled;
  • message list updates in real time;
  • unread/read state updates;
  • blocked users are filtered;
  • Firebase permission errors are visible in logs and do not leave a permanent spinner.

Troubleshooting

ProblemFix
Conversation screen loads foreverConfirm listener errors call the empty-state callback, then check Firestore rules and current user ID.
Messages do not sendDeploy Firebase Functions and check callable Function region/config.
User can read another user's chatTighten Firestore rules and validate channel participants.
Media messages failCheck src/core/media, Firebase Storage/Functions, and Blaze plan requirements for uploads.
Group chat crashesConfirm social graph/friends data is present and the group chat flag did not remove required screens.

Documentation updates

Keep your build moving

Get important setup notes, new guides, and useful product updates without a noisy weekly newsletter.