React Native SDK
Drop-in mobile chat UI for iOS and Android, built on the same headless core as the web kit.
@cariosan/react-native is the mobile UI kit — native components (View/FlatList/TextInput) rendering the same chat experience as the web kit. It reuses the framework-agnostic core: @cariosan/client (transport) and the DOM-free hooks from @cariosan/react run unchanged in React Native, so engagement features (quoted reply, @-mentions, read receipts, search) behave identically to web.
What the kit gives you — and what you build
The kit ships building blocks, not whole screens. That's deliberate: chat UX is app-specific, and we don't want to drag a navigation library, a media picker, or Firebase into your bundle. The kit stays dependency-light; you bring your own platform pieces.
In the kit (@cariosan/react-native + @cariosan/client) — the engine + reusable UI:
- Components:
MessageList,MessageInput,ChannelList,TypingIndicator,PresenceBadge. - Hooks:
useMessages(with reconnect resync),useChannels,usePresence,useReadReceipts,useMessageActions,useMessageSelection,useReplyDraft, … - All the logic on
client/channel: send / edit / delete, reactions, receipts, search, @-mentions, attachment upload, group avatars + roles (updateChannel/addMembers/setMemberRole/removeMember), presence (withrole),lastMessagepreview.
You build (the app layer) — what's UX- or platform-specific:
- Screens + navigation — chat list, chat room, group info, etc. Use any router (Expo Router, React Navigation, or a simple state switch); the kit doesn't impose one.
- Auth — get a user JWT from your backend. (The example's "paste a JWT" login is a test shim, not production auth.)
- Attachment picker UI — the kit gives you the hooks (
MessageInput'sonAttachPress+attachmentPreview+onSendAttachment, pluschannel.uploadAttachment); you supply the picker with the library you prefer (expo-image-picker,react-native-image-picker, …). - Push — register the token via
client.registerDevice(...); the Firebase / native wiring is yours (BYO).
The example is a reference, not a dependency
examples/mobile-react-native wires all of the above into a full app (chat list, group info, member actions, attachment panel). Copy its screens as a starting point — but they live in the example, not in the published @cariosan/* packages. A real app composes the kit the same way, with its own design.
Install
Provider
Wrap your app once. You own the SDK lifecycle (construct, connect, pause on background) — the provider just shares the client:
Components
MessageList— aFlatListof messages in a familiar chat layout: day separators (Today / Yesterday / date), left/right bubbles (received in slate, your own right-aligned in emerald), bottom-right time + ✓/✓✓/✓✓-blue read-receipt ticks on your own messages, plus @-mention highlighting, quoted-reply previews (tap to scroll to the original), reaction pills, and edited/tombstone states. Inside aMessageSelectionProvider, long-press a message to highlight it and float a quick-reactions row (❤️ 👍 😂 …) above it. Props:currentUserId(internal id or external_id) decides which bubbles are "yours";showSenderNames={false}hides the sender name on received bubbles for 1:1 chats (it shows by default, which suits group channels).MessageInput— text composer with an @-mention autocomplete (tap to insert; passmentionMembersor it lazily loads the roster), a 🙂 emoji inserter, a quote-reply chip, and a send button. PassonAttachPressto show a 📎 button — your handler picks a file and stages it viaattachmentPreview(a preview node) +onSendAttachment(caption), which fires when send is tapped (upload + send happen then, not on pick), e.g.channel.uploadAttachment(blob, { filename, mimeType })→sendMessage({ attachmentUrl }). InMessageList, image attachments render as thumbnails and other files as a tappable document card; emoji-only messages render large and bubble-less.ChannelList— the caller's channels with unread + mention badges.TypingIndicator,PresenceBadge— live presence/typing.
Hold-to-select: drive your own action bar
MessageList only renders the in-place highlight + quick-reactions. The contextual action bar (reply / copy / delete / …) is yours to render — read useMessageSelection() in your header and swap the title for actions while a message is held, WhatsApp-style:
deleteMessage is author-only (the server rejects deleting others' messages), so only show Delete when msg.user.id/external_id matches the current user. Copy needs a clipboard module — expo-clipboard works in Expo; the kit stays dependency-free.
Wrap your screen in a safe area
The kit components fill their parent and don't add device insets — that's the app's job. Without one, MessageInput's text field and send button sit behind the Android navigation bar (and the iOS home indicator) and can't be tapped. Use react-native-safe-area-context (bundled with Expo) — not react-native's SafeAreaView, which is iOS-only:
Hooks
The kit re-exports every hook from @cariosan/react (they're DOM-free) — useMessages, useMessageSender, useChannels, useTyping, usePresence, useConnectionStatus, useReadReceipts, useMentions, useReplyDraft, useSearch, plus ChatProvider/useCariosan. Build fully custom RN UI on the hooks while reusing all the subscription/cursor plumbing. See the React hooks reference — the API is identical.
Styling
Components ship a sensible dark-slate default styled with StyleSheet. React Native has no CSS, so theming is via standard RN style props / forking the components — there's no stylesheet import like the web kit.
One core, every platform
@cariosan/client and the hooks are the single source of truth. The web (@cariosan/react) and mobile (@cariosan/react-native) kits differ only in their rendered components — so a feature shipped to the core lands on both.
Was this page helpful?