{"id":"361c4ed0-83ea-4a2c-8389-bba94e2639c7","shortId":"Jspde8","kind":"skill","title":"cometchat-native-customization","tagline":"Customize the CometChat React Native UI Kit without forking — four-tier model: props → request builders → text formatters + message templates → DataSource decorators + event bus.","description":"## Purpose\n\nTeaches Claude how to change the behavior or appearance of the React Native UI Kit **without modifying the kit itself**. Four tiers, from cheapest to deepest:\n\n```\nTier 1 — Props            (95% of asks solved here)\nTier 2 — RequestBuilder   (filter what data loads)\nTier 3 — Formatters + Templates   (change how text / messages render)\nTier 4 — DataSource decorators + Events  (last resort, powerful)\n```\n\n**Always try Tier 1 first.** Escalate only when the tier can't do what the user wants.\n\n**Read `cometchat-native-components` first** — the catalog is the source of truth for prop names, slot views, and event listener names that this skill builds on.\n\nGround truth: `docs/ui-kit/react-native/custom-text-formatter-guide.mdx`, `mentions-formatter-guide.mdx`, `shortcut-formatter-guide.mdx`, `url-formatter-guide.mdx`, `events.mdx`, `methods.mdx`, `property-changes.mdx`, and the kit's source at `packages/ChatUiKit/src/shared/formatters/` and `packages/ChatUiKit/src/shared/events/`.\n\n---\n\n## Four-tier triage — pick the right tier before writing any code\n\nWhen a user says \"I want X\" for a CometChat component:\n\n| If they want to... | Use Tier | Cost |\n|---|---|---|\n| Hide a feature (thread option, receipts, edit, etc.) | Tier 1 — `hide*` / `*Visibility` props | 1 line of JSX |\n| Customize a subsection (header title, subtitle, avatar, empty state) | Tier 1 — `<Slot>View` prop | 1 component |\n| Filter what loads (only show online users, exclude blocked, include tags) | Tier 2 — `*RequestBuilder` | 1 builder |\n| Change how URLs / mentions / hashtags / emojis render inline | Tier 3 — `textFormatters` | Subclass of `CometChatTextFormatter` |\n| Render a custom message type (custom bubble, custom interactive msg) | Tier 3 — `templates` + `CometChatMessageTemplate` | 1 template + 1 renderer |\n| React to events from another component (\"they deleted a message, now reload my view\") | Tier 4 — `CometChatUIEventHandler` | Listener |\n| Rewrite how data flows through the kit (custom conversation sorting, override user-fetch logic) | Tier 4 — `DataSourceDecorator` | Class extension |\n\nIf a user's ask fits Tier 1 but you jumped to Tier 3, you've written 50 lines that a 1-line prop could have replaced. Start low.\n\n---\n\n## Tier 1 — Props (hide / slot views / styles)\n\n`cometchat-native-components` is the full catalog. Three prop families cover most customization:\n\n### 1a. `hide*` / `*Visibility` flags\n\nTurn features off with a single prop:\n\n```tsx\n<CometChatMessageList\n  user={selectedUser}\n  hideReplyInThreadOption     // already mandatory — see components § 11\n  hideReceipts\n  hideReactions={false}\n  hideTranslateMessageOption\n  hideMessagePrivatelyOption\n  hideReplyOption={false}\n/>\n```\n\nFull list of `hide*` props per component: `cometchat-native-components`. Check there before writing custom code.\n\n### 1b. `<Slot>View` props — replace a section\n\nEvery component has PascalCase slot props for replacing named sections of its default UI:\n\n```tsx\n<CometChatMessageHeader\n  user={selectedUser}\n  TitleView={(user, group) => <Text style={styles.customTitle}>{user?.getName()}</Text>}\n  SubtitleView={(user, group) => <OnlineStatus user={user} />}\n  LeadingView={(user, group) => <CustomAvatar user={user} />}\n  TrailingView={(user, group) => <CustomActions user={user} />}\n  AuxiliaryButtonView={(user, group) => <CometChatCallButtons user={user} group={group} />}\n/>\n```\n\nSlot functions receive the same data the default view would have (typically `user`, `group`, or a single entity). They return RN JSX.\n\n**For custom views that should match the theme**, use `useTheme()`:\n\n```tsx\nimport { useTheme } from \"@cometchat/chat-uikit-react-native\";\n\nfunction CustomTitle({ user }: any) {\n  const theme = useTheme();\n  return (\n    <Text style={{\n      color: theme.color.textPrimary,\n      fontFamily: theme.typography.heading3.fontFamily,\n      fontSize: theme.typography.heading3.fontSize,\n    }}>\n      {user?.getName()}\n    </Text>\n  );\n}\n```\n\nSee `cometchat-native-theming` § 8 for more on `useTheme()`.\n\n### 1c. `style={{ ... }}` prop — nested styling\n\nEach component accepts a nested-object `style` prop (see `cometchat-native-components` § 13):\n\n```tsx\n<CometChatConversations\n  style={{\n    containerStyle: { backgroundColor: \"#FAFAFA\" },\n    itemStyle: {\n      avatarStyle: { containerStyle: { borderRadius: 8 } },\n    },\n  }}\n/>\n```\n\nPrefer theme-level changes (via `cometchat-native-theming`) for app-wide color shifts; use `style={{}}` only for one-off overrides on a single component instance.\n\n---\n\n## Tier 2 — RequestBuilder filtering\n\nFor \"I want to show a subset of X\", use the matching `*RequestBuilder`. Never post-filter in-render.\n\n```tsx\nimport { CometChat } from \"@cometchat/chat-sdk-react-native\";\n\n// Only conversations in a specific tag group\n<CometChatConversations\n  conversationsRequestBuilder={\n    new CometChat.ConversationsRequestBuilder()\n      .setLimit(20)\n      .setUserTags([\"premium\"])\n      .setConversationType(CometChat.RECEIVER_TYPE.USER)\n  }\n/>\n\n// Only online users, exclude blocked\n<CometChatUsers\n  usersRequestBuilder={\n    new CometChat.UsersRequestBuilder()\n      .setLimit(30)\n      .setStatus(\"online\")\n      .setSearchKeyword(\"\")\n      .friendsOnly(false)\n  }\n/>\n\n// Only groups you've joined\n<CometChatGroups\n  groupsRequestBuilder={\n    new CometChat.GroupsRequestBuilder()\n      .setLimit(30)\n      .joinedOnly(true)\n  }\n/>\n\n// Message list — exclude system messages\n<CometChatMessageList\n  user={user}\n  messageRequestBuilder={\n    new CometChat.MessagesRequestBuilder()\n      .setUID(user.getUid())\n      .setLimit(30)\n      .setCategories([\"message\"])   // exclude \"call\", \"action\"\n      .hideReplies(false)\n  }\n  hideReplyInThreadOption\n/>\n```\n\nEach request builder is chainable. The `@cometchat/chat-sdk-react-native` exports the builder classes — import them from the SDK, not the UI Kit.\n\n### Finding the right method\n\nRequest builder methods are documented at `cometchat.com/docs/sdk/react-native` (or query the docs MCP). Common ones:\n\n| Builder | Useful methods |\n|---|---|\n| `ConversationsRequestBuilder` | `.setLimit(n)`, `.setUserTags([...])`, `.setGroupTags([...])`, `.setConversationType(type)`, `.withTags(true)`, `.withUserAndGroupTags(true)` |\n| `UsersRequestBuilder` | `.setLimit(n)`, `.setStatus(\"online\")`, `.setSearchKeyword(str)`, `.friendsOnly(bool)`, `.setTags([...])`, `.setUIDs([...])`, `.hideBlockedUsers(bool)` |\n| `GroupsRequestBuilder` | `.setLimit(n)`, `.setSearchKeyword(str)`, `.joinedOnly(bool)`, `.setTags([...])`, `.setGroupTypes([...])` |\n| `MessagesRequestBuilder` | `.setUID(uid)` / `.setGUID(guid)`, `.setLimit(n)`, `.setCategories([...])`, `.setTypes([...])`, `.hideReplies(bool)`, `.setTags([...])`, `.setParentMessageId(id)` |\n| `GroupMembersRequestBuilder` | `.setLimit(n)`, `.setSearchKeyword(str)`, `.setScopes([...])` |\n\n---\n\n## Tier 3 — Text formatters + message templates\n\nFor \"change how text or messages render\", Tier 3 is the right level. Two sub-patterns:\n\n### 3a. Custom text formatter — inline text patterns\n\n`CometChatTextFormatter` is an abstract base class for matching inline text patterns (hashtags, keywords, emoji shortcodes, custom tags) and replacing them with custom JSX.\n\n```tsx\nimport {\n  CometChatTextFormatter,\n  SuggestionItem,\n} from \"@cometchat/chat-uikit-react-native\";\nimport { CometChat } from \"@cometchat/chat-sdk-react-native\";\nimport { Text, View, StyleSheet } from \"react-native\";\n\nclass HashtagFormatter extends CometChatTextFormatter {\n  constructor() {\n    super();\n    this.setTrackingCharacter(\"#\");              // optional — triggers suggestion list\n    this.setRegexPatterns([/\\B#(\\w+)\\b/g]);       // all matches get formatted\n  }\n\n  // Called for each bubble's text; return string | JSX\n  getFormattedText(\n    inputText: string | null | React.ReactNode,\n  ): string | React.ReactNode {\n    if (typeof inputText !== \"string\") return inputText;\n    const parts = inputText.split(/(\\B#\\w+\\b)/g);\n    return (\n      <Text>\n        {parts.map((part, i) =>\n          part.match(/^#\\w+$/)\n            ? <Text key={i} style={styles.hashtag} onPress={() => openHashtag(part)}>{part}</Text>\n            : <Text key={i}>{part}</Text>,\n        )}\n      </Text>\n    );\n  }\n\n  // Optional — called before a message is sent. Transform the outgoing message.\n  handlePreMessageSend(message: CometChat.TextMessage): CometChat.TextMessage {\n    // e.g. attach the list of hashtags to the message metadata\n    return message;\n  }\n\n  // Optional — for suggestion-list support (triggered by `#`)\n  search(searchKey: string): void {\n    // Fetch matching hashtags from your backend, then:\n    // this.setSearchData([{ id: \"tag1\", title: \"#typescript\" }]);\n  }\n}\n\nconst styles = StyleSheet.create({\n  hashtag: { color: \"#2563EB\", fontWeight: \"600\" },\n});\n```\n\nRegister the formatter by passing it to both `CometChatMessageList` and `CometChatMessageComposer`:\n\n```tsx\nconst formatters = [\n  new CometChatMentionsFormatter(),   // keep the built-in ones\n  new CometChatUrlsFormatter(),\n  new HashtagFormatter(),             // add yours\n];\n\n<CometChatMessageList\n  user={selectedUser}\n  textFormatters={formatters}\n  hideReplyInThreadOption\n/>\n<CometChatMessageComposer\n  user={selectedUser}\n  textFormatters={formatters}\n/>\n```\n\n### 3b. Custom message template — entire custom bubble\n\nFor rendering a totally custom message type (interactive cards, scheduling, forms), use `CometChatMessageTemplate`.\n\n```tsx\nimport {\n  CometChatMessageTemplate,\n  CometChatUiKitConstants,\n} from \"@cometchat/chat-uikit-react-native\";\n\nconst pollTemplate = new CometChatMessageTemplate({\n  type: \"poll\",\n  category: CometChatUiKitConstants.MessageCategoryConstants.custom,\n  ContentView: (message, alignment) => (\n    <PollBubble message={message} alignment={alignment} />\n  ),\n  BottomView: (message, alignment) => (\n    <PollVoteCounts message={message} />\n  ),\n  options: (loggedInUser, message, group) => [\n    /* CometChatMessageOption[] — custom long-press menu items */\n  ],\n});\n\n<CometChatMessageList\n  user={selectedUser}\n  templates={[pollTemplate, ...defaultTemplates]}   // merge with defaults\n  hideReplyInThreadOption\n/>\n```\n\nGetting the default templates to merge with:\n\n```tsx\nimport { ChatConfigurator } from \"@cometchat/chat-uikit-react-native\";\nconst defaults = ChatConfigurator.getDataSource().getAllMessageTemplates();\n<CometChatMessageList templates={[pollTemplate, ...defaults]} />\n```\n\n### When to use text formatter vs message template\n\n| Use formatter (Tier 3a) | Use template (Tier 3b) |\n|---|---|\n| Change how TEXT inside a bubble renders (hashtags, URLs, mentions, emoji shortcodes) | Render a completely different bubble body |\n| Content is still a `TextMessage` | Content is a custom message type (sent via `CometChat.sendCustomMessage`) |\n| Doesn't need its own long-press options | Needs custom message options (vote, claim, accept, etc.) |\n\n---\n\n## Tier 4 — DataSource decorators + event bus\n\nWhen Tiers 1-3 can't do it, you're modifying how data flows through the UI Kit. Two mechanisms:\n\n### 4a. Event bus — `CometChatUIEventHandler`\n\nSubscribe to events that UI Kit components emit so your own code can react.\n\n```tsx\nimport { CometChatUIEventHandler } from \"@cometchat/chat-uikit-react-native\";\nimport { useEffect } from \"react\";\n\nfunction AppScreen() {\n  useEffect(() => {\n    const listenerId = \"APP_MESSAGE_LISTENER\";\n\n    CometChatUIEventHandler.addMessageListener(listenerId, {\n      ccMessageSent: ({ message, status }) => {\n        // status === \"inProgress\" | \"sent\"\n        analytics.track(\"message_sent\", { id: message.getId() });\n      },\n      ccMessageEdited: ({ message }) => { /* ... */ },\n      ccMessageDeleted: ({ message }) => { /* ... */ },\n      ccMessageRead: ({ message }) => { /* ... */ },\n      ccLiveReaction: ({ reaction }) => { /* ... */ },\n    });\n\n    return () => CometChatUIEventHandler.removeMessageListener(listenerId);\n  }, []);\n\n  return /* ... */;\n}\n```\n\n### Event listener API reference\n\n| Listener | Use when... |\n|---|---|\n| `addMessageListener` | reacting to any message-related event (sent, edited, deleted, read, reactions) |\n| `addConversationListener` | reacting to conversation-level events (`ccConversationDeleted`, `ccUpdateConversation`) |\n| `addUserListener` | reacting to user actions (`ccUserBlocked`, `ccUserUnblocked`) |\n| `addGroupListener` | reacting to group lifecycle (`ccGroupCreated`, `ccGroupDeleted`, `ccGroupLeft`, `ccGroupMemberScopeChanged`, `ccGroupMemberKicked`, `ccGroupMemberBanned`, `ccGroupMemberJoined`, `ccGroupMemberAdded`, `ccOwnershipChanged`, etc.) |\n| `addCallListener` | reacting to call events (`onIncomingCallAccepted`, `onCallEnded`, `onCallInitiated`, etc.) |\n\nEvery pair has a matching `remove*Listener(id)` — **always call it in the cleanup of your `useEffect`** to avoid duplicate listeners on re-render.\n\n**Listener ID uniqueness matters.** Use a constant per component/feature. Colliding IDs cause only the latest-registered listener to fire.\n\n### 4b. DataSource decorators\n\n`DataSourceDecorator` and `MessageDataSource` wrap the kit's internal data source to override specific methods without forking the whole kit.\n\nWhen to reach for this: overriding how user data is fetched, how conversations are sorted, adding custom message metadata to every sent message, intercepting attachment uploads.\n\nMinimum pattern:\n\n```tsx\nimport {\n  DataSource,\n  DataSourceDecorator,\n  ChatConfigurator,\n} from \"@cometchat/chat-uikit-react-native\";\n\nclass MyDataSource extends DataSourceDecorator {\n  constructor(source: DataSource) {\n    super(source);\n  }\n\n  // Override only the method you want to change\n  getConversationsRequestBuilder() {\n    const builder = super.getConversationsRequestBuilder();\n    builder.setUserAndGroupTags(true);\n    return builder;\n  }\n\n  getMessageTemplate() {\n    const defaults = super.getMessageTemplate();\n    return [myCustomTemplate, ...defaults];\n  }\n}\n\n// Register the decorator before init — wraps the default data source\nChatConfigurator.dataSource = new MyDataSource(ChatConfigurator.getDataSource());\nawait CometChatUIKit.init(settings);\n```\n\n**This is an escape hatch, not a first tool.** If you find yourself reaching for Tier 4, re-check whether Tier 1 (props) or Tier 3 (templates) could have solved it. Templates + slot views cover most \"custom behavior\" asks.\n\n### 4c. Extensions datasource (for extension-like deep behavior)\n\n`ExtensionsDataSource` is the base class for registering an extension-shaped chunk of behavior (its own composer action + its own bubble + its own data handling) — this is what `PollsExtension`, `StickersExtension`, etc. extend internally. You'd only subclass this if you're shipping a reusable feature module across apps.\n\nFor a single app, use `DataSourceDecorator` instead.\n\n---\n\n## 5. Sample app reference (when Tiers 1–4 don't have what you need)\n\nIf none of Tiers 1–4 covered the user's request, **don't immediately conclude they need custom code**. The RN UI Kit ships two reference sample apps that compose multiple kit components into common chat UX patterns that aren't shipped as named exports:\n\n> Bare RN: https://github.com/cometchat/cometchat-uikit-react-native/tree/v5/examples/SampleApp\n>\n> Expo:    https://github.com/cometchat/cometchat-uikit-react-native/tree/v5/examples/SampleAppExpo\n\n(Use the branch matching your installed UI-Kit major version — confirm via `package.json`. If the user is on v5, use `v5`; for v6 use `v6`. The folder layout is identical between the two flavors — `src/components`, `src/screens`, `src/utils` — so the same lookup table works for both.)\n\nExamples that look like \"missing components\" but are in the sample app:\n\n| User asks for | Sample app reference path |\n|---|---|\n| User / group details screen | `examples/SampleApp(Expo)/src/components/CometChatDetails/` (`CometChatUserDetails.tsx` + group-details inline in the home screen) |\n| Threaded messages screen layout | `examples/SampleApp(Expo)/src/components/CometChatDetails/CometChatThreadedMessages.tsx` |\n| Top-level chat shell (tabs + screens + drawer) | `examples/SampleApp(Expo)/src/components/CometChatHome/` + `App.tsx` |\n| Multi-tab chat (Chats / Calls / Users / Groups) | `examples/SampleApp(Expo)/src/components/CometChatTabs/` |\n| New conversation modal with user/group picker | `examples/SampleApp(Expo)/src/components/CometChatNewChat/` |\n| Search screen (conversations + messages) | `examples/SampleApp(Expo)/src/components/CometChatSearch/` |\n| Call log details / history / recordings | `examples/SampleApp(Expo)/src/components/CometChatCallLog/` |\n| App-state / active-chat React context | `examples/SampleApp(Expo)/src/context/AppContext.tsx` |\n\n**Discovery commands (works against either repo flavor):**\n\n```bash\n# List the sample app's components directory via the GitHub API (bare RN)\ncurl -s \"https://api.github.com/repos/cometchat/cometchat-uikit-react-native/contents/examples/SampleApp/src/components?ref=v5\" \\\n  | grep -oE '\"name\":\\s*\"[^\"]+\"' | head -30\n\n# Same, for Expo\ncurl -s \"https://api.github.com/repos/cometchat/cometchat-uikit-react-native/contents/examples/SampleAppExpo/src/components?ref=v5\" \\\n  | grep -oE '\"name\":\\s*\"[^\"]+\"' | head -30\n\n# Fetch a specific component file directly\ncurl -s \"https://raw.githubusercontent.com/cometchat/cometchat-uikit-react-native/v5/examples/SampleApp/src/components/CometChatDetails/CometChatUserDetails.tsx\"\n```\n\nYou can also use `WebFetch` on the URLs above. The docs MCP does NOT index the sample apps — fetch them from GitHub directly.\n\n**If you find a matching reference implementation:**\n\n1. Read the `.tsx` file. Note: RN sample-app components use `StyleSheet.create({...})` blocks colocated in the same file (no separate stylesheet file like the web sample app — RN doesn't have CSS).\n2. Mirror the sample's file/folder structure in the user's project, e.g. `src/cometchat/CometChatDetails/CometChatUserDetails.tsx`. Don't rename, don't simplify the structure — match it exactly so future patches against the sample apply cleanly.\n3. Adapt navigation: SampleApp uses React Navigation; if the user is on Expo Router, swap `navigation.navigate(...)` → `router.push(...)` and `useRoute()` → `useLocalSearchParams()`. Everything else carries over.\n4. The kit's `useTheme()` hook works identically inside copied sample components — keep the calls intact rather than hardcoding colors.\n\n---\n\n## 6. Recipes (common customization asks → right tier)\n\n### \"Filter the conversation list to just premium users\"\n**Tier 2** — `conversationsRequestBuilder` with `.setUserTags([\"premium\"])`.\n\n### \"Custom empty state for the users list\"\n**Tier 1** — `EmptyStateView` slot prop on `CometChatUsers`.\n\n### \"Custom message bubble for incoming messages only\"\n**Tier 3b** — `CometChatMessageTemplate` with a `ContentView` that branches on `alignment === \"receive\"`. Or simpler — **Tier 1** `messageListStyles.receiveBubbleStyle` in the theme (see `cometchat-native-theming` § 6).\n\n### \"Show a custom view when the user types @\"\n**Tier 3a** — subclass `CometChatMentionsFormatter` (or extend `CometChatTextFormatter`), implement `search(key)` + `setSearchData([...])` with your own suggestion source.\n\n### \"When a message is sent, log it to our analytics\"\n**Tier 4a** — `CometChatUIEventHandler.addMessageListener` with `ccMessageSent` handler.\n\n### \"When a group is deleted, remove it from my local cache + navigate away\"\n**Tier 4a** — `addGroupListener` with `ccGroupDeleted` handler.\n\n### \"Render custom avatars for all users based on their department\"\n**Tier 1** — `LeadingView` slot on `CometChatConversations` + `CometChatUsers` + `CometChatMessageHeader`.\n\n### \"Disable the file attachment option\"\n**Tier 1** — filter the `attachmentOptions` prop on `CometChatMessageComposer`:\n\n```tsx\n<CometChatMessageComposer\n  user={user}\n  attachmentOptions={(user, group) => {\n    const defaults = /* default actions from ChatConfigurator */;\n    return defaults.filter((opt) => opt.id !== \"attachment-file\");\n  }}\n/>\n```\n\n### \"Show only message types that contain the word 'urgent'\"\n**Tier 2** — `messageRequestBuilder` with `.setSearchKeyword(\"urgent\")`.\n\n### \"Custom message type: a 'ping' message\"\n**Tier 3b** — create a `CometChatMessageTemplate` with `category: \"custom\"` + `type: \"ping\"`, render a custom `ContentView`, send via `CometChat.sendCustomMessage`.\n\n### \"Completely replace the kit's conversation-loading logic\"\n**Tier 4b** — `DataSourceDecorator` overriding `getConversationsRequestBuilder()` + possibly wrapping the fetch itself. Rare. Try Tier 2 first.\n\n---\n\n## 6. Anti-patterns\n\n1. **Don't hand-roll a bubble when a template will do.** `CometChatMessageTemplate` (Tier 3b) gives you full control over rendering + options without losing theming, reactions, typing, receipts.\n\n2. **Don't post-filter a list's data after render.** If you want \"only online users,\" use Tier 2 `usersRequestBuilder.setStatus(\"online\")` — don't fetch everyone then hide rows.\n\n3. **Don't forget to remove listeners in `useEffect` cleanup.** RN re-renders on every navigation can register duplicate listeners; each fires your handler once per registration.\n\n4. **Don't collide listener IDs.** Use `APP_MESSAGE_LISTENER` or `${componentName}_MESSAGE_LISTENER` — constant, unique. Colliding IDs silently drop earlier registrations.\n\n5. **Don't put `CometChatTextFormatter` instances in component state.** Construct them once at module scope (or in a `useMemo`); re-creating them on every render loses the internal suggestion state.\n\n6. **Don't fork or patch `@cometchat/chat-uikit-react-native` directly.** Every customization should be possible via Tiers 1-4. Forking breaks on kit upgrades.\n\n7. **Don't reach for Tier 4 before trying 1-3.** DataSource decorators are powerful but fragile to kit internal changes. Props, request builders, and templates are stable surface area.\n\n8. **Don't change component behavior via monkey-patching (e.g., `Component.defaultProps = ...`).** Use the actual prop API. Monkey-patching is broken by design in React 19+.\n\n---\n\n## 7. Wiring a custom formatter end-to-end (full working example)\n\nSay the user wants `:emoji:` shortcodes (e.g., `:smile:` → 😀):\n\n```tsx\n// 1. Define the formatter — module scope, constructed once\nimport { CometChatTextFormatter } from \"@cometchat/chat-uikit-react-native\";\nimport { Text } from \"react-native\";\n\nconst EMOJI_MAP: Record<string, string> = {\n  \":smile:\": \"😀\", \":heart:\": \"❤️\", \":thumbsup:\": \"👍\", \":fire:\": \"🔥\",\n};\n\nclass EmojiShortcodeFormatter extends CometChatTextFormatter {\n  constructor() {\n    super();\n    this.setRegexPatterns([/:[a-z_]+:/g]);\n  }\n\n  getFormattedText(input: string | null | React.ReactNode) {\n    if (typeof input !== \"string\") return input;\n    const parts = input.split(/(:[a-z_]+:)/g);\n    return (\n      <Text>\n        {parts.map((p, i) =>\n          EMOJI_MAP[p] ? <Text key={i}>{EMOJI_MAP[p]}</Text> : <Text key={i}>{p}</Text>,\n        )}\n      </Text>\n    );\n  }\n}\n\n// 2. Build the formatters array at module scope\nimport { CometChatMentionsFormatter, CometChatUrlsFormatter } from \"@cometchat/chat-uikit-react-native\";\nexport const TEXT_FORMATTERS = [\n  new CometChatMentionsFormatter(),\n  new CometChatUrlsFormatter(),\n  new EmojiShortcodeFormatter(),\n];\n\n// 3. Wire into list + composer (same array — must match)\nimport { TEXT_FORMATTERS } from \"./formatters\";\n<CometChatMessageList user={user} textFormatters={TEXT_FORMATTERS} hideReplyInThreadOption />\n<CometChatMessageComposer user={user} textFormatters={TEXT_FORMATTERS} />\n```\n\n---\n\n## Skill routing reference\n\n| Skill | When to route |\n|---|---|\n| `cometchat-native-core` | Init / login / provider chain |\n| `cometchat-native-components` | Prop reference — which `hide*`, `<Slot>View`, `*RequestBuilder` is available (prerequisite for Tiers 1–2) |\n| `cometchat-native-placement` | Where to put the customized components |\n| `cometchat-native-theming` | App-wide color / typography / dark mode — Tier 1 alternative to `style={{}}` |\n| `cometchat-native-features` | Which out-of-the-box features exist (so you know what needs customizing vs. what's already there) |\n| `cometchat-native-customization` | This skill — four-tier triage + custom formatters / templates / DataSource / events |\n| `cometchat-native-production` | When customization depends on production auth (token refresh, user-ID mapping) |\n| `cometchat-native-troubleshooting` | Formatter doesn't apply, listener fires twice, slot view renders nothing, template not showing |","tags":["cometchat","native","customization","skills","agent-skills","ai-agent","chat","claude-code","cursor","messaging","nextjs","react"],"capabilities":["skill","source-cometchat","skill-cometchat-native-customization","topic-agent-skills","topic-ai-agent","topic-chat","topic-claude-code","topic-cometchat","topic-cursor","topic-messaging","topic-nextjs","topic-react","topic-react-native","topic-ui-kit"],"categories":["cometchat-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cometchat/cometchat-skills/cometchat-native-customization","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cometchat/cometchat-skills","source_repo":"https://github.com/cometchat/cometchat-skills","install_from":"skills.sh"}},"qualityScore":"0.463","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 27 github stars · SKILL.md body (24,488 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:04:54.319Z","embedding":null,"createdAt":"2026-05-07T13:05:14.523Z","updatedAt":"2026-05-18T19:04:54.319Z","lastSeenAt":"2026-05-18T19:04:54.319Z","tsv":"'-3':1169,2387 '-30':1806,1820 '-4':2371 '/cometchat/cometchat-uikit-react-native/tree/v5/examples/sampleapp':1624 '/cometchat/cometchat-uikit-react-native/tree/v5/examples/sampleappexpo':1628 '/cometchat/cometchat-uikit-react-native/v5/examples/sampleapp/src/components/cometchatdetails/cometchatuserdetails.tsx':1831 '/docs/sdk/react-native':706 '/formatters':2565 '/g':888,2493,2511 '/repos/cometchat/cometchat-uikit-react-native/contents/examples/sampleapp/src/components?ref=v5':1800 '/repos/cometchat/cometchat-uikit-react-native/contents/examples/sampleappexpo/src/components?ref=v5':1814 '/src/components/cometchatcalllog':1763 '/src/components/cometchatdetails':1700 '/src/components/cometchatdetails/cometchatthreadedmessages.tsx':1716 '/src/components/cometchathome':1727 '/src/components/cometchatnewchat':1748 '/src/components/cometchatsearch':1755 '/src/components/cometchattabs':1739 '/src/context/appcontext.tsx':1774 '1':57,91,189,193,207,210,226,256,258,305,319,328,1168,1479,1567,1579,1862,2001,2028,2109,2122,2215,2370,2386,2455,2609,2633 '11':368 '13':535 '19':2433 '1a':348 '1b':393 '1c':516 '2':65,224,577,1895,1988,2159,2209,2244,2264,2529,2610 '20':617 '2563eb':964 '3':72,237,253,311,771,784,1483,1928,2274,2552 '30':632,648,665 '3a':793,1106,2048 '3b':1006,1110,2015,2171,2230 '4':81,275,294,1161,1473,1568,1580,1952,2302,2383 '4a':1186,2074,2093 '4b':1351,2197 '4c':1497 '5':1561,2324 '50':315 '6':1972,2038,2211,2355 '600':966 '7':2377,2434 '8':511,546,2407 '95':59 'a-z':2490,2508 'abstract':803 'accept':523,1158 'across':1552 'action':670,1279,1523,2139 'activ':1768 'active-chat':1767 'actual':2421 'ad':1388 'adapt':1929 'add':993 'addcalllisten':1297 'addconversationlisten':1266 'addgrouplisten':1282,2094 'addmessagelisten':1253 'adduserlisten':1275 'align':1042,1046,1047,1050,2023 'alreadi':364,2658 'also':1834 'altern':2634 'alway':88,1314 'analyt':2072 'analytics.track':1229 'anoth':264 'anti':2213 'anti-pattern':2212 'api':1248,1793,2423 'api.github.com':1799,1813 'api.github.com/repos/cometchat/cometchat-uikit-react-native/contents/examples/sampleapp/src/components?ref=v5':1798 'api.github.com/repos/cometchat/cometchat-uikit-react-native/contents/examples/sampleappexpo/src/components?ref=v5':1812 'app':559,1218,1553,1557,1563,1602,1686,1691,1765,1786,1849,1871,1889,2309,2626 'app-stat':1764 'app-wid':558,2625 'app.tsx':1728 'appear':38 'appli':1926,2698 'appscreen':1214 'area':2406 'aren':1614 'array':2533,2558 'ask':61,302,1496,1688,1976 'attach':924,1397,2119,2147 'attachment-fil':2146 'attachmentopt':2125,2133 'auth':2684 'auxiliarybuttonview':443 'avail':2605 'avatar':203,2100 'avatarstyl':543 'avoid':1324 'await':1454 'away':2091 'b':853,885,887 'b/g':855 'backend':952 'backgroundcolor':540 'bare':1620,1794 'base':804,1509,2104 'bash':1782 'behavior':36,1495,1505,1519,2412 'block':220,626,1875 'bodi':1128 'bool':736,740,747,760 'borderradius':545 'bottomview':1048 'box':2646 'branch':1631,2021 'break':2373 'broken':2428 'bubbl':248,863,1012,1116,1127,1526,2009,2222 'build':130,2530 'builder':20,227,676,683,699,714,1427,1432,2400 'builder.setuserandgrouptags':1429 'built':986 'built-in':985 'bus':28,1165,1188 'cach':2089 'call':669,860,909,1300,1315,1734,1756,1966 'card':1021 'carri':1950 'catalog':112,341 'categori':1038,2176 'caus':1342 'ccconversationdelet':1273 'ccgroupcreat':1287 'ccgroupdelet':1288,2096 'ccgroupleft':1289 'ccgroupmemberad':1294 'ccgroupmemberban':1292 'ccgroupmemberjoin':1293 'ccgroupmemberkick':1291 'ccgroupmemberscopechang':1290 'cclivereact':1240 'ccmessagedelet':1236 'ccmessageedit':1234 'ccmessageread':1238 'ccmessages':1223,2077 'ccownershipchang':1295 'ccupdateconvers':1274 'ccuserblock':1280 'ccuserunblock':1281 'chain':2593 'chainabl':678 'chang':34,75,228,551,777,1111,1424,2397,2410 'chat':1610,1720,1732,1733,1769 'chatconfigur':1084,1405,2141 'chatconfigurator.datasource':1450 'chatconfigurator.getdatasource':1089,1453 'cheapest':53 'check':387,1476 'chunk':1517 'claim':1157 'class':296,684,805,841,1408,1510,2483 'claud':31 'clean':1927 'cleanup':1319,2283 'code':161,392,1201,1593 'collid':1340,2305,2318 'coloc':1876 'color':498,561,963,1971,2628 'cometchat':2,7,107,171,335,384,508,532,554,602,830,2035,2587,2595,2612,2622,2638,2661,2676,2692 'cometchat-native-compon':106,334,383,531,2594 'cometchat-native-cor':2586 'cometchat-native-custom':1,2660 'cometchat-native-featur':2637 'cometchat-native-plac':2611 'cometchat-native-product':2675 'cometchat-native-them':507,553,2034,2621 'cometchat-native-troubleshoot':2691 'cometchat.com':705 'cometchat.com/docs/sdk/react-native':704 'cometchat.conversationsrequestbuilder':615 'cometchat.groupsrequestbuilder':646 'cometchat.messagesrequestbuilder':661 'cometchat.receiver_type.user':621 'cometchat.sendcustommessage':1142,2186 'cometchat.textmessage':921,922 'cometchat.usersrequestbuilder':630 'cometchat/chat-sdk-react-native':604,680,832 'cometchat/chat-uikit-react-native':487,828,1031,1086,1208,1407,2361,2466,2541 'cometchatcallbutton':446 'cometchatconvers':537,612,2113 'cometchatgroup':643 'cometchatmentionsformatt':982,2050,2538,2547 'cometchatmessagecompos':977,1001,2128,2130,2573 'cometchatmessagehead':414,2115 'cometchatmessagelist':360,656,975,995,1065,1091,2566 'cometchatmessageopt':1058 'cometchatmessagetempl':255,1025,1028,1035,2016,2174,2228 'cometchattextformatt':241,800,825,844,2053,2328,2464,2486 'cometchatuieventhandl':276,1189,1206 'cometchatuieventhandler.addmessagelistener':1221,2075 'cometchatuieventhandler.removemessagelistener':1243 'cometchatuikit.init':1455 'cometchatuikitconst':1029 'cometchatuikitconstants.messagecategoryconstants.custom':1039 'cometchaturlsformatt':990,2539,2549 'cometchatus':627,2006,2114 'cometchatuserdetails.tsx':1701 'command':1776 'common':712,1609,1974 'complet':1125,2187 'compon':109,172,211,265,337,367,382,386,400,522,534,574,1196,1607,1680,1788,1824,1872,1963,2331,2411,2597,2620 'component.defaultprops':2418 'component/feature':1339 'componentnam':2313 'compos':1522,1604,2556 'conclud':1589 'confirm':1640 'const':492,882,959,979,1032,1087,1216,1426,1434,2136,2473,2505,2543 'constant':1337,2316 'construct':2333,2461 'constructor':845,1412,2487 'contain':2154 'containerstyl':539,544 'content':1129,1134 'contentview':1040,2019,2183 'context':1771 'control':2234 'convers':286,606,1270,1385,1741,1751,1981,2193 'conversation-level':1269 'conversation-load':2192 'conversationsrequestbuild':613,717,1989 'copi':1961 'core':2589 'cost':179 'could':322,1485 'cover':345,1492,1581 'creat':2172,2345 'css':1894 'curl':1796,1810,1827 'custom':4,5,197,244,247,249,285,347,391,474,794,815,821,1007,1011,1017,1059,1137,1153,1389,1494,1592,1975,1993,2007,2041,2099,2164,2177,2182,2364,2437,2619,2654,2663,2670,2680 'customact':440 'customavatar':434 'customtitl':489 'd':1540 'dark':2630 'data':69,280,456,1178,1362,1381,1448,1529,2253 'datasourc':25,82,1162,1352,1403,1414,1499,2388,2673 'datasourcedecor':295,1354,1404,1411,1559,2198 'decor':26,83,1163,1353,1442,2389 'deep':1504 'deepest':55 'default':411,458,1073,1077,1088,1094,1435,1439,1447,2137,2138 'defaults.filter':2143 'defaulttempl':1070 'defin':2456 'delet':267,1263,2083 'depart':2107 'depend':2681 'design':2430 'detail':1696,1704,1758 'differ':1126 'direct':1826,1854,2362 'directori':1789 'disabl':2116 'discoveri':1775 'doc':710,1842 'docs/ui-kit/react-native/custom-text-formatter-guide.mdx':134 'document':702 'doesn':1143,1891,2696 'drawer':1724 'drop':2321 'duplic':1325,2293 'e.g':923,1907,2417,2452 'earlier':2322 'edit':186,1262 'either':1779 'els':1949 'emit':1197 'emoji':233,813,1121,2450,2474,2516,2522 'emojishortcodeformatt':2484,2551 'empti':204,1994 'emptystateview':2002 'end':2440,2442 'end-to-end':2439 'entir':1010 'entiti':468 'escal':93 'escap':1460 'etc':187,1159,1296,1305,1536 'event':27,84,124,262,1164,1187,1192,1246,1260,1272,1301,2674 'events.mdx':138 'everi':399,1306,1393,2289,2348,2363 'everyon':2270 'everyth':1948 'exact':1919 'exampl':1675,2445 'examples/sampleapp':1698,1714,1725,1737,1746,1753,1761,1772 'exclud':219,625,653,668 'exist':2648 'expo':1625,1699,1715,1726,1738,1747,1754,1762,1773,1809,1940 'export':681,1619,2542 'extend':843,1410,1537,2052,2485 'extens':297,1498,1502,1515 'extension-lik':1501 'extension-shap':1514 'extensionsdatasourc':1506 'fafafa':541 'fals':371,375,637,672 'famili':344 'featur':182,353,1550,2640,2647 'fetch':291,947,1383,1821,1850,2204,2269 'file':1825,1866,1880,1884,2118,2148 'file/folder':1900 'filter':67,212,579,596,1979,2123,2249 'find':694,1468,1857 'fire':1350,2296,2482,2700 'first':92,110,1464,2210 'fit':303 'flag':351 'flavor':1663,1781 'flow':281,1179 'folder':1656 'fontfamili':500 'fontsiz':502 'fontweight':965 'forget':2277 'fork':13,1369,2358,2372 'form':1023 'format':859 'formatt':22,73,773,796,969,980,999,1005,1099,1104,2438,2458,2532,2545,2563,2571,2578,2671,2695 'four':15,50,151,2667 'four-tier':14,150,2666 'fragil':2393 'friendson':636,735 'full':340,376,2233,2443 'function':452,488,1213 'futur':1921 'get':858,1075 'getallmessagetempl':1090 'getconversationsrequestbuild':1425,2200 'getformattedtext':869,2494 'getmessagetempl':1433 'getnam':424,505 'github':1792,1853 'github.com':1623,1627 'github.com/cometchat/cometchat-uikit-react-native/tree/v5/examples/sampleapp':1622 'github.com/cometchat/cometchat-uikit-react-native/tree/v5/examples/sampleappexpo':1626 'give':2231 'grep':1801,1815 'ground':132 'group':419,427,433,439,445,449,450,464,611,639,1057,1285,1695,1703,1736,2081,2135 'group-detail':1702 'groupmembersrequestbuild':764 'groupsrequestbuild':644,741 'guid':754 'hand':2219 'hand-rol':2218 'handl':1530 'handlepremessagesend':919 'handler':2078,2097,2298 'hardcod':1970 'hashtag':232,811,928,949,962,1118 'hashtagformatt':842,992 'hatch':1461 'head':1805,1819 'header':200 'heart':2480 'hide':180,190,330,349,379,2272,2601 'hideblockedus':739 'hidemessageprivatelyopt':373 'hidereact':370 'hidereceipt':369 'hiderepli':671,759 'hidereplyinthreadopt':363,673,1000,1074,2572 'hidereplyopt':374 'hidetranslatemessageopt':372 'histori':1759 'home':1708 'hook':1957 'id':763,955,1232,1313,1332,1341,2307,2319,2689 'ident':1659,1959 'immedi':1588 'implement':1861,2054 'import':484,601,685,824,829,833,1027,1083,1205,1209,1402,2463,2467,2537,2561 'in-rend':597 'includ':221 'incom':2011 'index':1846 'init':1444,2590 'inlin':235,797,808,1705 'inprogress':1227 'input':2495,2501,2504 'input.split':2507 'inputtext':870,878,881 'inputtext.split':884 'insid':1114,1960 'instal':1634 'instanc':575,2329 'instead':1560 'intact':1967 'interact':250,1020 'intercept':1396 'intern':1361,1538,2352,2396 'item':1064 'itemstyl':542 'join':642 'joinedon':649,746 'jsx':196,472,822,868 'jump':308 'keep':983,1964 'key':896,905,2056,2520,2526 'keyword':812 'kit':11,44,48,143,284,693,1183,1195,1359,1372,1597,1606,1637,1954,2190,2375,2395 'know':2651 'last':85 'latest':1346 'latest-regist':1345 'layout':1657,1713 'leadingview':431,2110 'level':550,788,1271,1719 'lifecycl':1286 'like':1503,1678,1885 'line':194,316,320 'list':377,652,851,926,939,1783,1982,1999,2251,2555 'listen':125,277,1220,1247,1250,1312,1326,1331,1348,2280,2294,2306,2311,2315,2699 'listenerid':1217,1222,1244 'load':70,214,2194 'local':2088 'log':1757,2068 'loggedinus':1055 'logic':292,2195 'login':2591 'long':1061,1149 'long-press':1060,1148 'look':1677 'lookup':1670 'lose':2239,2350 'low':326 'major':1638 'mandatori':365 'map':2475,2517,2523,2690 'match':478,591,807,857,948,1310,1632,1859,1917,2560 'matter':1334 'mcp':711,1843 'mechan':1185 'mention':231,1120 'mentions-formatter-guide.mdx':135 'menu':1063 'merg':1071,1080 'messag':23,78,245,269,651,655,667,774,781,912,918,920,931,934,1008,1018,1041,1044,1045,1049,1052,1053,1056,1101,1138,1154,1219,1224,1230,1235,1237,1239,1258,1390,1395,1711,1752,2008,2012,2065,2151,2165,2169,2310,2314 'message-rel':1257 'message.getid':1233 'messagedatasourc':1356 'messageliststyles.receivebubblestyle':2029 'messagerequestbuild':659,2160 'messagesrequestbuild':750 'metadata':932,1391 'method':697,700,716,1367,1420 'methods.mdx':139 'minimum':1399 'mirror':1896 'miss':1679 'modal':1742 'mode':2631 'model':17 'modifi':46,1176 'modul':1551,2337,2459,2535 'monkey':2415,2425 'monkey-patch':2414,2424 'msg':251 'multi':1730 'multi-tab':1729 'multipl':1605 'must':2559 'mycustomtempl':1438 'mydatasourc':1409,1452 'n':719,730,743,756,766 'name':120,126,407,1618,1803,1817 'nativ':3,9,42,108,336,385,509,533,555,840,2036,2472,2588,2596,2613,2623,2639,2662,2677,2693 'navig':1930,1934,2090,2290 'navigation.navigate':1943 'need':1145,1152,1574,1591,2653 'nest':519,526 'nested-object':525 'never':593 'new':614,629,645,660,981,989,991,1034,1451,1740,2546,2548,2550 'none':1576 'note':1867 'noth':2705 'null':872,2497 'object':527 'oe':1802,1816 'oncallend':1303 'oncalliniti':1304 'one':568,713,988 'one-off':567 'onincomingcallaccept':1302 'onlin':217,623,634,732,2260,2266 'onlinestatus':428 'onpress':900 'openhashtag':901 'opt':2144 'opt.id':2145 'option':184,848,908,935,1054,1151,1155,2120,2237 'out-of-the-box':2642 'outgo':917 'overrid':288,570,1365,1378,1417,2199 'p':2514,2518,2524,2528 'package.json':1642 'packages/chatuikit/src/shared/events':149 'packages/chatuikit/src/shared/formatters':147 'pair':1307 'part':883,891,902,903,907,2506 'part.match':893 'parts.map':890,2513 'pascalcas':402 'pass':971 'patch':1922,2360,2416,2426 'path':1693 'pattern':792,799,810,1400,1612,2214 'per':381,1338,2300 'pick':154 'picker':1745 'ping':2168,2179 'placement':2614 'poll':1037 'pollbubbl':1043 'pollsextens':1534 'polltempl':1033,1069,1093 'pollvotecount':1051 'possibl':2201,2367 'post':595,2248 'post-filt':594,2247 'power':87,2391 'prefer':547 'premium':619,1985,1992 'prerequisit':2606 'press':1062,1150 'product':2678,2683 'project':1906 'prop':18,58,119,192,209,321,329,343,358,380,395,404,518,529,1480,2004,2126,2398,2422,2598 'property-changes.mdx':140 'provid':2592 'purpos':29 'put':2327,2617 'queri':708 'rare':2206 'rather':1968 'raw.githubusercontent.com':1830 'raw.githubusercontent.com/cometchat/cometchat-uikit-react-native/v5/examples/sampleapp/src/components/cometchatdetails/cometchatuserdetails.tsx':1829 're':1175,1329,1475,1546,2286,2344 're-check':1474 're-creat':2343 're-rend':1328,2285 'reach':1375,1470,2380 'react':8,41,260,839,1203,1212,1254,1267,1276,1283,1298,1770,1933,2432,2471 'react-nat':838,2470 'react.reactnode':873,875,2498 'reaction':1241,1265,2241 'read':105,1264,1863 'receipt':185,2243 'receiv':453,2024 'recip':1973 'record':1760,2476 'refer':1249,1564,1600,1692,1860,2581,2599 'refresh':2686 'regist':967,1347,1440,1512,2292 'registr':2301,2323 'relat':1259 'reload':271 'remov':1311,2084,2279 'renam':1911 'render':79,234,242,259,599,782,1014,1117,1123,1330,2098,2180,2236,2255,2287,2349,2704 'replac':324,396,406,818,2188 'repo':1780 'request':19,675,698,1585,2399 'requestbuild':66,225,578,592,2603 'resort':86 'return':470,495,866,880,889,933,1242,1245,1431,1437,2142,2503,2512 'reusabl':1549 'rewrit':278 'right':156,696,787,1977 'rn':471,1595,1621,1795,1868,1890,2284 'roll':2220 'rout':2580,2585 'router':1941 'router.push':1944 'row':2273 'sampl':1562,1601,1685,1690,1785,1848,1870,1888,1898,1925,1962 'sample-app':1869 'sampleapp':1931 'say':165,2446 'schedul':1022 'scope':2338,2460,2536 'screen':1697,1709,1712,1723,1750 'sdk':689 'search':943,1749,2055 'searchkey':944 'section':398,408 'see':366,506,530,2033 'selectedus':362,416,997,1003,1067 'send':2184 'sent':914,1140,1228,1231,1261,1394,2067 'separ':1882 'set':1456 'setcategori':666,757 'setconversationtyp':620,722 'setgrouptag':721 'setgrouptyp':749 'setguid':753 'setlimit':616,631,647,664,718,729,742,755,765 'setparentmessageid':762 'setscop':769 'setsearchdata':2057 'setsearchkeyword':635,733,744,767,2162 'setstatus':633,731 'settag':737,748,761 'settyp':758 'setuid':662,738,751 'setusertag':618,720,1991 'shape':1516 'shell':1721 'shift':562 'ship':1547,1598,1616 'shortcod':814,1122,2451 'shortcut-formatter-guide.mdx':136 'show':216,584,2039,2149,2708 'silent':2320 'simpler':2026 'simplifi':1914 'singl':357,467,573,1556 'skill':129,2579,2582,2665 'skill-cometchat-native-customization' 'slot':121,331,403,451,1490,2003,2111,2702 'smile':2453,2479 'solv':62,1487 'sort':287,1387 'sourc':115,145,1363,1413,1416,1449,2062 'source-cometchat' 'specif':609,1366,1823 'src/cometchat/cometchatdetails/cometchatuserdetails.tsx':1908 'src/components':1664 'src/screens':1665 'src/utils':1666 'stabl':2404 'start':325 'state':205,1766,1995,2332,2354 'status':1225,1226 'stickersextens':1535 'still':1131 'str':734,745,768 'string':867,871,874,879,945,2477,2478,2496,2502 'structur':1901,1916 'style':333,421,497,517,520,528,538,564,898,960,2636 'styles.customtitle':422 'styles.hashtag':899 'stylesheet':836,1883 'stylesheet.create':961,1874 'sub':791 'sub-pattern':790 'subclass':239,1542,2049 'subscrib':1190 'subsect':199 'subset':586 'subtitl':202 'subtitleview':425 'suggest':850,938,2061,2353 'suggestion-list':937 'suggestionitem':826 'super':846,1415,2488 'super.getconversationsrequestbuilder':1428 'super.getmessagetemplate':1436 'support':940 'surfac':2405 'swap':1942 'system':654 'tab':1722,1731 'tabl':1671 'tag':222,610,816 'tag1':956 'teach':30 'templat':24,74,254,257,775,1009,1068,1078,1092,1102,1108,1484,1489,2225,2402,2672,2706 'text':21,77,420,496,772,779,795,798,809,834,865,895,904,1098,1113,2468,2519,2525,2544,2562,2570,2577 'textformatt':238,998,1004,2569,2576 'textmessag':1133 'theme':480,493,510,549,556,2032,2037,2240,2624 'theme-level':548 'theme.color.textprimary':499 'theme.typography.heading3.fontfamily':501 'theme.typography.heading3.fontsize':503 'this.setregexpatterns':852,2489 'this.setsearchdata':954 'this.settrackingcharacter':847 'thread':183,1710 'three':342 'thumbsup':2481 'tier':16,51,56,64,71,80,90,97,152,157,178,188,206,223,236,252,274,293,304,310,327,576,770,783,1105,1109,1160,1167,1472,1478,1482,1566,1578,1978,1987,2000,2014,2027,2047,2073,2092,2108,2121,2158,2170,2196,2208,2229,2263,2369,2382,2608,2632,2668 'titl':201,957 'titleview':417 'token':2685 'tool':1465 'top':1718 'top-level':1717 'topic-agent-skills' 'topic-ai-agent' 'topic-chat' 'topic-claude-code' 'topic-cometchat' 'topic-cursor' 'topic-messaging' 'topic-nextjs' 'topic-react' 'topic-react-native' 'topic-ui-kit' 'total':1016 'trailingview':437 'transform':915 'tri':89,2207,2385 'triag':153,2669 'trigger':849,941 'troubleshoot':2694 'true':650,725,727,1430 'truth':117,133 'tsx':359,413,483,536,600,823,978,1026,1082,1204,1401,1865,2129,2454 'turn':352 'twice':2701 'two':789,1184,1599,1662 'type':246,723,1019,1036,1139,2046,2152,2166,2178,2242 'typeof':877,2500 'typescript':958 'typic':462 'typographi':2629 'ui':10,43,412,692,1182,1194,1596,1636 'ui-kit':1635 'uid':752 'uniqu':1333,2317 'upgrad':2376 'upload':1398 'urgent':2157,2163 'url':230,1119,1839 'url-formatter-guide.mdx':137 'use':177,481,563,589,715,1024,1097,1103,1107,1251,1335,1558,1629,1649,1653,1835,1873,1932,2262,2308,2419 'useeffect':1210,1215,1322,2282 'uselocalsearchparam':1947 'usememo':2342 'user':103,164,218,290,300,361,415,418,423,426,429,430,432,435,436,438,441,442,444,447,448,463,490,504,624,657,658,996,1002,1066,1278,1380,1583,1645,1687,1694,1735,1904,1937,1986,1998,2045,2103,2131,2132,2134,2261,2448,2567,2568,2574,2575,2688 'user-fetch':289 'user-id':2687 'user.getuid':663 'user/group':1744 'userout':1946 'usersrequestbuild':628,728 'usersrequestbuilder.setstatus':2265 'usethem':482,485,494,515,1956 'ux':1611 'v5':1648,1650 'v6':1652,1654 've':313,641 'version':1639 'via':552,1141,1641,1790,2185,2368,2413 'view':122,208,273,332,394,459,475,835,1491,2042,2602,2703 'visibl':191,350 'void':946 'vote':1156 'vs':1100,2655 'w':854,886,894 'want':104,167,175,582,1422,2258,2449 'web':1887 'webfetch':1836 'whether':1477 'whole':1371 'wide':560,2627 'wire':2435,2553 'without':12,45,1368,2238 'withtag':724 'withuserandgrouptag':726 'word':2156 'work':1672,1777,1958,2444 'would':460 'wrap':1357,1445,2202 'write':159,390 'written':314 'x':168,588 'z':2492,2510","prices":[{"id":"4fd4e09a-4485-4b08-9d3c-41378d251df8","listingId":"361c4ed0-83ea-4a2c-8389-bba94e2639c7","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cometchat","category":"cometchat-skills","install_from":"skills.sh"},"createdAt":"2026-05-07T13:05:14.523Z"}],"sources":[{"listingId":"361c4ed0-83ea-4a2c-8389-bba94e2639c7","source":"github","sourceId":"cometchat/cometchat-skills/cometchat-native-customization","sourceUrl":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-native-customization","isPrimary":false,"firstSeenAt":"2026-05-07T13:05:14.523Z","lastSeenAt":"2026-05-18T19:04:54.319Z"}],"details":{"listingId":"361c4ed0-83ea-4a2c-8389-bba94e2639c7","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cometchat","slug":"cometchat-native-customization","github":{"repo":"cometchat/cometchat-skills","stars":27,"topics":["agent-skills","ai-agent","chat","claude-code","cometchat","cursor","messaging","nextjs","react","react-native","ui-kit"],"license":null,"html_url":"https://github.com/cometchat/cometchat-skills","pushed_at":"2026-05-18T05:04:24Z","description":"Add CometChat chat to any React, Next.js, React Native, Angular, Android, iOS, or Flutter project through your AI coding agent. Works with Claude Code, Cursor, Codex, VS Code Copilot, Windsurf, Cline, Kiro, and 50+ more agents.","skill_md_sha":"f298b15564841cafbdf959c5d58b4aa30b5fac7b","skill_md_path":"skills/cometchat-native-customization/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-native-customization"},"layout":"multi","source":"github","category":"cometchat-skills","frontmatter":{"name":"cometchat-native-customization","license":"MIT","description":"Customize the CometChat React Native UI Kit without forking — four-tier model: props → request builders → text formatters + message templates → DataSource decorators + event bus.","compatibility":"Node.js >=18; React Native >=0.70; @cometchat/chat-uikit-react-native ^5"},"skills_sh_url":"https://skills.sh/cometchat/cometchat-skills/cometchat-native-customization"},"updatedAt":"2026-05-18T19:04:54.319Z"}}