cometchat-react-native-placement
SkillAI & modelsWhere the CometChat React Native UI Kit v5 surfaces go in a real app, one screen per route on a stack navigator, tab-based layouts, growing from the core surface to the full app, and embedding chat in an existing screen. Triggers: add a chat tab React Native, chat screen navigation RN, react-navigation CometChat, embed chat in my RN app, full chat app layout.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the cometchat-react-native-placement skill
What this skill tells your AI
The instructions your AI receives, as published by cometchat/cometchat-skills in skills/cometchat-react-native-placement/SKILL.md and read by ahel’s review.
Ground truth:
@cometchat/chat-uikit-react-native@5+ catalogrn-v5.json. Docs:/ui-kit/react-native/react-native-conversation·react-native-tab-based-chat·expo-tab-based-chat. Fetch props viacore/references/docs-map.md.
Companion skills (read first)
cometchat-react-native-core— install, provider chain, init→login→render. Assumed, not repeated here.
Use this skill when
- "add a chat tab" · "put chat on its own screen" · "chat inside my existing app"
- "build the whole chat app" · "how do I navigate from the list to a conversation"
Prerequisites & install
Navigation is not bundled. The documented stack:
npm install @react-navigation/native @react-navigation/native-stack @react-navigation/bottom-tabs
npm install react-native-screens react-native-safe-area-context
⚠️ Align these to YOUR React Native version — do not take the latest. The UI Kit declares its peers
as "*", so nothing constrains them for you. react-native-screens 4.x / safe-area-context 5.x use
Fabric codegen that RN 0.77's @react-native/codegen cannot parse; Metro then fails with
Unknown prop type for "moduleId" / "onFinishTransitioning" — an error naming a native codegen file,
never CometChat. Run npx react-native doctor, or match a known-good set for your RN
(on 0.77: gesture-handler@2.32.0 + screens@4.4.0 + safe-area-context@4.14.0).
The rule that governs every layout: one screen per route
This is the single biggest difference from the web UI Kit. React places a list and a message pane side by side and toggles side panels with state. On a phone that is wrong:
- each surface is its own screen on a stack navigator
- navigation is
navigation.navigate(...), not conditional rendering - back is the hardware/gesture back button — the OS provides it; do not hand-roll one
- there are no side panels. Search, thread and details are screens you push.
Conditional rendering ({selected ? <Chat/> : <List/>}) appears in the simplest docs recipe and is
fine for a single-screen demo, but it breaks the Android back button and loses navigation state.
Anything beyond a demo uses the navigator.
Provider chain vs navigator — order matters
Providers wrap the navigator, not the other way round. GestureHandlerRootView stays outermost:
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { NavigationContainer } from "@react-navigation/native";
import {
CometChatI18nProvider, CometChatThemeProvider,
} from "@cometchat/chat-uikit-react-native";
export const Root = ({ children }: { children: React.ReactNode }) => (
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaProvider>
<CometChatI18nProvider>
<CometChatThemeProvider>
<NavigationContainer>{children}</NavigationContainer>
</CometChatThemeProvider>
</CometChatI18nProvider>
</SafeAreaProvider>
</GestureHandlerRootView>
);
Putting NavigationContainer outside the providers means screens mount without a theme and the kit
falls back to defaults.
Placement 1 — chat on its own screen (the default)
Two routes: the list, and the message pane. This is what an unscoped "add chat" should produce.
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { CometChatConversations } from "@cometchat/chat-uikit-react-native";
const Stack = createNativeStackNavigator();
const ConversationsScreen = () => <CometChatConversations />;
const MessagesScreen = () => null; // header + list + composer — see `core`
export const ChatStack = () => (
<Stack.Navigator>
<Stack.Screen name="Conversations" component={ConversationsScreen} />
<Stack.Screen name="Messages" component={MessagesScreen} options={{ headerShown: false }} />
</Stack.Navigator>
);
headerShown: false on the message screen because CometChatMessageHeader is the header —
leaving the native header on gives you two stacked headers.
The list screen navigates on onItemPress; the message screen reads user/group from route params,
sets showBackButton (it defaults to false on RN) and wires onBack to navigation.goBack().
Placement 2 — a chat tab in an existing app
Chat becomes one tab beside your own screens. The bottom-tab navigator holds the tabs; a stack sits above it so the message screen covers the tab bar when a conversation opens.
<Stack.Navigator>
<Stack.Screen name="Tabs" component={TabNavigator} options={{ headerShown: false }} />
<Stack.Screen name="Messages" component={MessagesScreen} options={{ headerShown: false }} />
</Stack.Navigator>;
If Messages lives inside the tab navigator instead, the tab bar stays visible over the composer —
the classic "keyboard and tab bar fighting" bug.
Placement 3 — grow to the full app
Add tabs for the other directories as they are asked for, each its own screen:
CometChatConversations (Chats) · CometChatUsers (Users) · CometChatGroups (Groups) ·
CometChatCallLogs (Calls). Push, don't panel:
| Surface | How it appears |
|---|---|
| thread replies | push a screen with CometChatThreadHeader |
| search | push a screen with CometChatSearch, wire onBack |
| group members | push a screen with CometChatGroupMembers |
| user/group details | you build this — kit v5 ships no details component (SDK fallback, see core/references/docs-map.md) |
CometChatIncomingCall is the exception: mount it once above the navigator so a call can arrive
on any screen.
Placement 4 — embed in an existing screen
Chat as part of a screen rather than the whole of it. The container must still be flex: 1 with
minHeight: 0; a fixed height breaks when the keyboard opens.
Sizing and the keyboard
Every ancestor of a kit component is flex: 1. A scrolling column also needs minHeight: 0. Verify
with the keyboard open — the composer must stay visible, which a simulator can mislead you about.
Common pitfalls
- Two headers —
headerShown: falseon any screen usingCometChatMessageHeader. - Message screen inside the tab navigator — tab bar overlaps the composer.
- Side panels ported from web — push a screen instead.
NavigationContaineroutside the providers — screens mount unthemed.- Hand-rolled back buttons — use the navigator's; wire
onBacktonavigation.goBack(). CometChatIncomingCallinside one screen — calls then only arrive on that screen.
Verify it works
- Every emitted component appears in
catalogs/rn-v5.json. npm run verify:fences:rn-v5is green.- On device: hardware back returns from the message screen; opening search/thread and pressing back returns cleanly; the composer survives the keyboard; a call arrives while on any tab.
Signals
- GitHub stars
- 109
- Forks
- 2
- Last commit
- Sep 2026
ahel review
K1binfo
installs-packages
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
cometchat-react-native-placement- Source
- github.com/cometchat/cometchat-skills