@cometchat/skills 4.2.1 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +33 -12
  3. package/bin/install.js +59 -4
  4. package/package.json +14 -1
  5. package/skills/cometchat/SKILL.md +460 -77
  6. package/skills/cometchat/references/asking-questions.md +48 -0
  7. package/skills/cometchat-a11y/SKILL.md +3 -2
  8. package/skills/cometchat-android-v5/SKILL.md +2 -1
  9. package/skills/cometchat-android-v5-calls/SKILL.md +36 -22
  10. package/skills/cometchat-android-v5-calls/references/README.md +1 -1
  11. package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +7 -5
  12. package/skills/cometchat-android-v5-calls/references/audio-controls.md +4 -4
  13. package/skills/cometchat-android-v5-calls/references/call-layouts.md +33 -25
  14. package/skills/cometchat-android-v5-calls/references/call-session.md +2 -2
  15. package/skills/cometchat-android-v5-calls/references/custom-ui.md +5 -5
  16. package/skills/cometchat-android-v5-calls/references/event-listeners.md +2 -2
  17. package/skills/cometchat-android-v5-calls/references/idle-timeout.md +20 -14
  18. package/skills/cometchat-android-v5-calls/references/in-call-chat.md +1 -1
  19. package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +43 -27
  20. package/skills/cometchat-android-v5-calls/references/participant-management.md +3 -3
  21. package/skills/cometchat-android-v5-calls/references/raise-hand.md +25 -19
  22. package/skills/cometchat-android-v5-calls/references/recording.md +2 -2
  23. package/skills/cometchat-android-v5-calls/references/ringing-integration.md +1 -1
  24. package/skills/cometchat-android-v5-calls/references/screen-sharing.md +5 -9
  25. package/skills/cometchat-android-v5-calls/references/session-settings.md +3 -3
  26. package/skills/cometchat-android-v5-calls/references/setup.md +1 -1
  27. package/skills/cometchat-android-v5-calls/references/share-invite.md +9 -4
  28. package/skills/cometchat-android-v5-calls/references/video-controls.md +4 -4
  29. package/skills/cometchat-android-v5-calls/references/voip-calling.md +2 -2
  30. package/skills/cometchat-android-v5-components/SKILL.md +4 -3
  31. package/skills/cometchat-android-v5-core/SKILL.md +20 -2
  32. package/skills/cometchat-android-v5-customization/SKILL.md +171 -7
  33. package/skills/cometchat-android-v5-extensions/SKILL.md +7 -4
  34. package/skills/cometchat-android-v5-features/SKILL.md +5 -4
  35. package/skills/cometchat-android-v5-placement/SKILL.md +2 -1
  36. package/skills/cometchat-android-v5-production/SKILL.md +2 -1
  37. package/skills/cometchat-android-v5-push/SKILL.md +2 -3
  38. package/skills/cometchat-android-v5-testing/SKILL.md +2 -1
  39. package/skills/cometchat-android-v5-theming/SKILL.md +2 -1
  40. package/skills/cometchat-android-v5-troubleshooting/SKILL.md +3 -2
  41. package/skills/cometchat-android-v6/SKILL.md +2 -1
  42. package/skills/cometchat-android-v6-builder-settings/SKILL.md +11 -7
  43. package/skills/cometchat-android-v6-calls/SKILL.md +79 -18
  44. package/skills/cometchat-android-v6-calls/references/advanced-features.md +87 -0
  45. package/skills/cometchat-android-v6-calls/references/call-layouts.md +24 -15
  46. package/skills/cometchat-android-v6-calls/references/call-session.md +2 -2
  47. package/skills/cometchat-android-v6-calls/references/device-management.md +17 -16
  48. package/skills/cometchat-android-v6-calls/references/idle-timeout.md +7 -4
  49. package/skills/cometchat-android-v6-calls/references/in-call-chat.md +13 -8
  50. package/skills/cometchat-android-v6-calls/references/raise-hand.md +6 -4
  51. package/skills/cometchat-android-v6-compose-components/SKILL.md +52 -29
  52. package/skills/cometchat-android-v6-compose-customization/SKILL.md +156 -1
  53. package/skills/cometchat-android-v6-compose-placement/SKILL.md +129 -40
  54. package/skills/cometchat-android-v6-compose-theming/SKILL.md +27 -1
  55. package/skills/cometchat-android-v6-core/SKILL.md +389 -9
  56. package/skills/cometchat-android-v6-events/SKILL.md +4 -1
  57. package/skills/cometchat-android-v6-extensions/SKILL.md +2 -1
  58. package/skills/cometchat-android-v6-features/SKILL.md +26 -2
  59. package/skills/cometchat-android-v6-kotlin-components/SKILL.md +31 -1
  60. package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +172 -1
  61. package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +20 -5
  62. package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +36 -5
  63. package/skills/cometchat-android-v6-migration/SKILL.md +44 -42
  64. package/skills/cometchat-android-v6-production/SKILL.md +6 -3
  65. package/skills/cometchat-android-v6-push/SKILL.md +43 -2
  66. package/skills/cometchat-android-v6-testing/SKILL.md +11 -8
  67. package/skills/cometchat-android-v6-troubleshooting/SKILL.md +26 -5
  68. package/skills/cometchat-angular-calls/SKILL.md +256 -389
  69. package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +3 -2
  70. package/skills/cometchat-angular-calls/references/call-layouts.md +29 -12
  71. package/skills/cometchat-angular-calls/references/call-session.md +2 -2
  72. package/skills/cometchat-angular-calls/references/custom-ui.md +18 -10
  73. package/skills/cometchat-angular-calls/references/device-management.md +53 -34
  74. package/skills/cometchat-angular-calls/references/group-calls.md +45 -24
  75. package/skills/cometchat-angular-calls/references/idle-timeout.md +31 -15
  76. package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +7 -6
  77. package/skills/cometchat-angular-calls/references/raise-hand.md +9 -4
  78. package/skills/cometchat-angular-calls/references/recording-screen-share.md +32 -39
  79. package/skills/cometchat-angular-calls/references/ringing-integration.md +3 -1
  80. package/skills/cometchat-angular-calls/references/share-invite.md +11 -5
  81. package/skills/cometchat-angular-calls/references/virtual-background.md +29 -0
  82. package/skills/cometchat-angular-components/SKILL.md +149 -620
  83. package/skills/cometchat-angular-core/SKILL.md +235 -293
  84. package/skills/cometchat-angular-customization/SKILL.md +415 -223
  85. package/skills/cometchat-angular-features/SKILL.md +216 -334
  86. package/skills/cometchat-angular-patterns/SKILL.md +168 -359
  87. package/skills/cometchat-angular-placement/SKILL.md +189 -560
  88. package/skills/cometchat-angular-production/SKILL.md +241 -92
  89. package/skills/cometchat-angular-push/SKILL.md +280 -294
  90. package/skills/cometchat-angular-testing/SKILL.md +430 -158
  91. package/skills/cometchat-angular-theming/SKILL.md +190 -265
  92. package/skills/cometchat-angular-troubleshooting/SKILL.md +192 -157
  93. package/skills/cometchat-astro-patterns/SKILL.md +22 -1
  94. package/skills/cometchat-calls/SKILL.md +25 -19
  95. package/skills/cometchat-calls/references/use-case-broadcast.md +15 -10
  96. package/skills/cometchat-calls/references/use-case-marketplace.md +2 -3
  97. package/skills/cometchat-calls/references/use-case-support.md +3 -4
  98. package/skills/cometchat-calls/references/use-case-team.md +23 -12
  99. package/skills/cometchat-calls/references/use-case-telehealth.md +3 -4
  100. package/skills/cometchat-components/SKILL.md +163 -25
  101. package/skills/cometchat-core/SKILL.md +412 -13
  102. package/skills/cometchat-customization/SKILL.md +50 -25
  103. package/skills/cometchat-features/SKILL.md +313 -34
  104. package/skills/cometchat-flutter-v5/SKILL.md +10 -4
  105. package/skills/cometchat-flutter-v5-calls/SKILL.md +188 -158
  106. package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +48 -24
  107. package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +20 -15
  108. package/skills/cometchat-flutter-v5-calls/references/call-session.md +100 -145
  109. package/skills/cometchat-flutter-v5-calls/references/device-management.md +12 -8
  110. package/skills/cometchat-flutter-v5-calls/references/group-calls.md +30 -36
  111. package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +15 -13
  112. package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +12 -9
  113. package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +115 -65
  114. package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +41 -30
  115. package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +17 -14
  116. package/skills/cometchat-flutter-v5-calls/references/share-invite.md +8 -2
  117. package/skills/cometchat-flutter-v5-conversations/SKILL.md +2 -1
  118. package/skills/cometchat-flutter-v5-core/SKILL.md +20 -2
  119. package/skills/cometchat-flutter-v5-customization/SKILL.md +136 -5
  120. package/skills/cometchat-flutter-v5-events/SKILL.md +2 -1
  121. package/skills/cometchat-flutter-v5-messages/SKILL.md +2 -1
  122. package/skills/cometchat-flutter-v5-production/SKILL.md +15 -6
  123. package/skills/cometchat-flutter-v5-push/SKILL.md +2 -1
  124. package/skills/cometchat-flutter-v5-testing/SKILL.md +17 -6
  125. package/skills/cometchat-flutter-v5-theming/SKILL.md +2 -1
  126. package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +7 -6
  127. package/skills/cometchat-flutter-v5-users-groups/SKILL.md +3 -2
  128. package/skills/cometchat-flutter-v6/SKILL.md +17 -16
  129. package/skills/cometchat-flutter-v6-calls/SKILL.md +78 -63
  130. package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +8 -6
  131. package/skills/cometchat-flutter-v6-calls/references/advanced-features.md +89 -0
  132. package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +15 -12
  133. package/skills/cometchat-flutter-v6-calls/references/call-session.md +2 -2
  134. package/skills/cometchat-flutter-v6-calls/references/device-management.md +9 -3
  135. package/skills/cometchat-flutter-v6-calls/references/group-calls.md +10 -10
  136. package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +15 -7
  137. package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +6 -3
  138. package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +23 -16
  139. package/skills/cometchat-flutter-v6-components/SKILL.md +32 -11
  140. package/skills/cometchat-flutter-v6-conversations/SKILL.md +39 -11
  141. package/skills/cometchat-flutter-v6-core/SKILL.md +348 -10
  142. package/skills/cometchat-flutter-v6-customization/SKILL.md +97 -25
  143. package/skills/cometchat-flutter-v6-events/SKILL.md +3 -2
  144. package/skills/cometchat-flutter-v6-features/SKILL.md +15 -6
  145. package/skills/cometchat-flutter-v6-messages/SKILL.md +111 -60
  146. package/skills/cometchat-flutter-v6-migration/SKILL.md +18 -25
  147. package/skills/cometchat-flutter-v6-placement/SKILL.md +79 -50
  148. package/skills/cometchat-flutter-v6-production/SKILL.md +13 -12
  149. package/skills/cometchat-flutter-v6-push/SKILL.md +43 -21
  150. package/skills/cometchat-flutter-v6-testing/SKILL.md +6 -6
  151. package/skills/cometchat-flutter-v6-theming/SKILL.md +38 -5
  152. package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +182 -17
  153. package/skills/cometchat-flutter-v6-users-groups/SKILL.md +12 -4
  154. package/skills/cometchat-i18n/SKILL.md +139 -78
  155. package/skills/cometchat-ios/SKILL.md +4 -2
  156. package/skills/cometchat-ios-calls/SKILL.md +225 -95
  157. package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +11 -9
  158. package/skills/cometchat-ios-calls/references/audio-modes-and-controls.md +45 -0
  159. package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +6 -7
  160. package/skills/cometchat-ios-calls/references/call-layouts.md +31 -91
  161. package/skills/cometchat-ios-calls/references/call-session.md +51 -54
  162. package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +33 -29
  163. package/skills/cometchat-ios-calls/references/custom-ui.md +38 -38
  164. package/skills/cometchat-ios-calls/references/group-calls.md +33 -70
  165. package/skills/cometchat-ios-calls/references/idle-timeout.md +24 -25
  166. package/skills/cometchat-ios-calls/references/in-call-chat.md +19 -23
  167. package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +128 -70
  168. package/skills/cometchat-ios-calls/references/picture-in-picture.md +20 -20
  169. package/skills/cometchat-ios-calls/references/raise-hand.md +14 -227
  170. package/skills/cometchat-ios-calls/references/recording-screen-share.md +35 -122
  171. package/skills/cometchat-ios-calls/references/ringing-integration.md +17 -16
  172. package/skills/cometchat-ios-calls/references/share-invite.md +8 -12
  173. package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +4 -4
  174. package/skills/cometchat-ios-components/SKILL.md +200 -12
  175. package/skills/cometchat-ios-core/SKILL.md +281 -11
  176. package/skills/cometchat-ios-customization/SKILL.md +276 -110
  177. package/skills/cometchat-ios-features/SKILL.md +64 -36
  178. package/skills/cometchat-ios-placement/SKILL.md +15 -12
  179. package/skills/cometchat-ios-production/SKILL.md +12 -4
  180. package/skills/cometchat-ios-push/SKILL.md +53 -19
  181. package/skills/cometchat-ios-testing/SKILL.md +14 -9
  182. package/skills/cometchat-ios-theming/SKILL.md +39 -3
  183. package/skills/cometchat-ios-troubleshooting/SKILL.md +41 -21
  184. package/skills/cometchat-native-bare-patterns/SKILL.md +56 -18
  185. package/skills/cometchat-native-calls/SKILL.md +89 -19
  186. package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +2 -2
  187. package/skills/cometchat-native-calls/references/call-layouts.md +15 -14
  188. package/skills/cometchat-native-calls/references/call-session.md +2 -2
  189. package/skills/cometchat-native-calls/references/custom-ui.md +12 -8
  190. package/skills/cometchat-native-calls/references/device-management.md +53 -30
  191. package/skills/cometchat-native-calls/references/group-calls.md +35 -30
  192. package/skills/cometchat-native-calls/references/idle-timeout.md +6 -6
  193. package/skills/cometchat-native-calls/references/in-call-chat.md +10 -8
  194. package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +2 -2
  195. package/skills/cometchat-native-calls/references/raise-hand.md +15 -13
  196. package/skills/cometchat-native-calls/references/recording-screen-share.md +49 -170
  197. package/skills/cometchat-native-calls/references/share-invite.md +7 -5
  198. package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +4 -2
  199. package/skills/cometchat-native-components/SKILL.md +91 -57
  200. package/skills/cometchat-native-core/SKILL.md +281 -9
  201. package/skills/cometchat-native-customization/SKILL.md +150 -28
  202. package/skills/cometchat-native-expo-patterns/SKILL.md +77 -27
  203. package/skills/cometchat-native-features/SKILL.md +79 -49
  204. package/skills/cometchat-native-placement/SKILL.md +19 -10
  205. package/skills/cometchat-native-production/SKILL.md +9 -3
  206. package/skills/cometchat-native-push/SKILL.md +2 -1
  207. package/skills/cometchat-native-testing/SKILL.md +1 -2
  208. package/skills/cometchat-native-theming/SKILL.md +54 -29
  209. package/skills/cometchat-native-troubleshooting/SKILL.md +71 -3
  210. package/skills/cometchat-nextjs-patterns/SKILL.md +48 -6
  211. package/skills/cometchat-placement/SKILL.md +42 -3
  212. package/skills/cometchat-production/SKILL.md +12 -5
  213. package/skills/cometchat-react-calls/SKILL.md +220 -10
  214. package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +4 -3
  215. package/skills/cometchat-react-calls/references/call-layouts.md +5 -6
  216. package/skills/cometchat-react-calls/references/call-session.md +1 -1
  217. package/skills/cometchat-react-calls/references/custom-ui.md +61 -15
  218. package/skills/cometchat-react-calls/references/device-management.md +55 -51
  219. package/skills/cometchat-react-calls/references/group-calls.md +18 -23
  220. package/skills/cometchat-react-calls/references/idle-timeout.md +25 -12
  221. package/skills/cometchat-react-calls/references/in-call-chat.md +7 -7
  222. package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +9 -11
  223. package/skills/cometchat-react-calls/references/raise-hand.md +14 -14
  224. package/skills/cometchat-react-calls/references/recording-screen-share.md +39 -38
  225. package/skills/cometchat-react-calls/references/ringing-integration.md +2 -2
  226. package/skills/cometchat-react-calls/references/share-invite.md +4 -5
  227. package/skills/cometchat-react-calls/references/testing-calls-on-web.md +20 -2
  228. package/skills/cometchat-react-calls/references/virtual-background.md +32 -0
  229. package/skills/cometchat-react-patterns/SKILL.md +57 -4
  230. package/skills/cometchat-react-push/SKILL.md +258 -72
  231. package/skills/cometchat-react-router-patterns/SKILL.md +43 -4
  232. package/skills/cometchat-react-testing/SKILL.md +14 -5
  233. package/skills/cometchat-theming/SKILL.md +181 -18
  234. package/skills/cometchat-troubleshooting/SKILL.md +40 -20
@@ -1,15 +1,16 @@
1
1
  ---
2
2
  name: cometchat-react-calls
3
- description: CometChat Calls SDK integration for web React apps (Vite, CRA, Next.js, React Router, Astro). Covers @cometchat/calls-sdk-javascript install, dual-SDK init (Chat SDK + Calls SDK), getRTCToken, the kit's CometChatIncomingCall / CometChatOutgoingCall / CometChatOngoingCall components, CallButtons composition, getUserMedia permissions, browser TURN/STUN handling, and additive-vs-standalone modes.
3
+ description: CometChat Calls SDK integration for web React apps (Vite, CRA, Next.js, React Router, Astro). Covers @cometchat/calls-sdk-javascript install, dual-SDK init (Chat SDK + Calls SDK), generateToken (v4's getRTCToken was removed in v5), the kit's CometChatIncomingCall / CometChatOutgoingCall / CometChatOngoingCall components, CallButtons composition, getUserMedia permissions, browser TURN/STUN handling, and additive-vs-standalone modes.
4
4
  license: "MIT"
5
5
  compatibility: "React >= 18, Next.js >= 13, React Router v6/v7, Astro >= 4; @cometchat/calls-sdk-javascript ^5 (v5.0.0 stable shipped; pin to `@5` because the npm `latest` dist-tag still points at v4.2.6 — see §Install); @cometchat/chat-sdk-javascript ^4.x; @cometchat/chat-uikit-react ^6.x (additive mode)"
6
- allowed-tools: "shell, file-read, file-search, file-list, ask-user"
7
6
  metadata:
8
7
  author: "CometChat"
9
8
  version: "4.0.0"
10
9
  tags: "cometchat react calls voice video webrtc nextjs react-router astro getRTCToken getusermedia browser-permissions vite cra"
11
10
  ---
12
11
 
12
+ > **Ground truth:** `@cometchat/chat-uikit-react@^6` (+ `@cometchat/calls-sdk-javascript@^5`) — installed package types + `ui-kit/react`. **Official docs:** https://www.cometchat.com/docs/calls/javascript/overview · **Docs MCP:** `claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp` (or fetch the URL directly without MCP). Verify symbols against the installed package/source before relying on them.
13
+
13
14
  ## ⚠️ STOP — mandatory precondition before any code
14
15
 
15
16
  **Before writing one line of code, you MUST resolve `mode = ringing | session`.** This decides which entire integration shape you scaffold — they don't share UI, navigation, or surface.
@@ -80,6 +81,25 @@ If you can't use flex (e.g. fixed-height modal), just give the container explici
80
81
 
81
82
  ---
82
83
 
84
+ ## ⚠️ Idle timeout is in MILLISECONDS (the "Are you still there? → instant exit" bug)
85
+
86
+ The idle-timeout values are **milliseconds, not seconds.** This is the single most common calls-config footgun (customer-reported 2026-06): setting `idleTimeoutPeriodBeforePrompt: 180` thinking "180 seconds" means **180 ms** — so the moment you join a session alone, the "Are you still there?" prompt fires and the call exits in a fraction of a second.
87
+
88
+ ```ts
89
+ // ✗ WRONG — read as 180ms / 30ms → prompt + exit almost instantly on join
90
+ const settings = { idleTimeoutPeriodBeforePrompt: 180, idleTimeoutPeriodAfterPrompt: 30 };
91
+
92
+ // ✓ RIGHT — milliseconds. (defaults: 60_000 / 120_000)
93
+ const settings = {
94
+ idleTimeoutPeriodBeforePrompt: 180_000, // 180s before the prompt
95
+ idleTimeoutPeriodAfterPrompt: 60_000, // 60s grace before disconnect
96
+ };
97
+ ```
98
+
99
+ Set them as `SessionSettings` **object fields** (used with `joinSession(token, settings, container)`): `{ idleTimeoutPeriodBeforePrompt: 180_000, idleTimeoutPeriodAfterPrompt: 60_000 }`. ⚠️ There are **no** `setIdleTimeoutPeriodBeforePrompt`/`AfterPrompt` builder methods — `CallSettingsBuilder` has only a single `setIdleTimeoutPeriod(ms)`; the before/after split exists **only** as the two object fields. **`idleTimeoutPeriodAfterPrompt` has a 60_000 ms (60s) minimum** — smaller values are silently clamped to 60s. To effectively disable it, use a huge value (`86_400_000` = 24h), never `0` or a tiny number. The timer only counts down when you're the **only** participant — so a single-person session/test triggers it fastest. Full recipe (prompt UI + extend/leave): `references/idle-timeout.md`.
100
+
101
+ ---
102
+
83
103
  ## ⚠️ Next.js / SSR — mandatory bundler config
84
104
 
85
105
  Both SDKs ship code that **breaks Next.js's SSR pass**:
@@ -217,10 +237,25 @@ Production-grade voice + video calling for React-family web apps. Loaded by `com
217
237
  - Framework-specific patterns: `cometchat-react-patterns` / `cometchat-nextjs-patterns` / `cometchat-react-router-patterns` / `cometchat-astro-patterns`
218
238
 
219
239
  **Ground truth:**
220
- - SDK source — `~/Downloads/calls-sdk/calls-sdk-javascript-5/package/`
221
- - Sample apps — `~/Downloads/calls-sdk/calls-sdk-javascript-5/sample-apps/{react,vue,angular,svelte,ionic}/`
240
+ - SDK source — `calls-sdk-javascript-5/package/`
241
+ - Sample apps — `calls-sdk-javascript-5/sample-apps/{react,vue,angular,svelte,ionic}/`
222
242
  - Public docs — https://www.cometchat.com/docs/calls/javascript/overview
223
243
 
244
+ ## When to use
245
+
246
+ - React-family web apps with voice/video calling: Vite + React, Next.js (App or Pages Router), React Router v6/v7, Astro with React islands.
247
+ - The user wants 1:1 OR group calls AND wants the calls UI surface (not pure server-side / signaling-only).
248
+ - Either calling mode applies — ringing (kit-driven incoming call screen) OR session (meeting-room URL pattern).
249
+
250
+ ## When NOT to use
251
+
252
+ - **Chat-only integrations (no calling at all)** — skip this skill entirely. Load only `cometchat-core` + `cometchat-react-patterns` + `cometchat-components`. Don't install `@cometchat/calls-sdk-javascript` — the calls SDK alone is ~700 KB; with the kit + chat SDK the full production bundle of a chat-**and**-calls app is ~4.8 MB JS (verified — real `vite build`). That's expected; a green build also emits benign `COMMONJS_VARIABLE_IN_ESM` warnings from the calls SDK's own code and a >500 KB chunk-size warning — these are NOT failures.
253
+ - **Native mobile (Android / iOS / RN / Flutter)** — load the cohort-specific calls skill (`cometchat-native-calls`, `cometchat-android-v6-calls`, `cometchat-ios-calls`, `cometchat-flutter-v6-calls`). The Calls SDK is platform-specific; APIs and lifecycle differ.
254
+ - **Angular** — load `cometchat-angular-calls`. Same underlying JS Calls SDK but wrapped in Angular Services + `@Output()` event bindings (NOT React-style callback props — verified runtime smoke 2026-06-02 caught the v4→v5 binding inversion).
255
+ - **SDK-only (no UI Kit)** — `cometchat-react-calls` §4c covers the SDK-only path in detail; this is the right skill, but you're using a specific subset. Don't import `<CometChatCallButtons>` / `<CometChatOngoingCall>` / `<CometChatIncomingCall>` from `@cometchat/chat-uikit-react` in that mode.
256
+ - **Server-side token-mint server work** — load `cometchat-production` for the REST-API token recipes; this skill is client-side.
257
+ - **Visual Builder calls** — load `cometchat-core` §11 + the framework-specific patterns; the Visual Builder generates calls wiring differently.
258
+
224
259
  ---
225
260
 
226
261
  ## 1. The seven hard rules — web specialization
@@ -242,11 +277,13 @@ const initiated = await CometChat.initiateCall(outgoing);
242
277
  // ✓ RIGHT — join WebRTC session (Calls SDK v5)
243
278
  import { CometChatCalls } from "@cometchat/calls-sdk-javascript";
244
279
 
245
- // v5 — plain SessionSettings object, no Builder
280
+ // v5 — plain SessionSettings object, no Builder.
281
+ // `as const` keeps the string literals narrow ("VIDEO"/"TILE") so they satisfy
282
+ // the SDK's SessionType / Layout unions — a bare object widens them to `string`.
246
283
  const sessionSettings = {
247
284
  sessionType: "VIDEO", // or "VOICE"
248
285
  layout: "TILE",
249
- };
286
+ } as const;
250
287
 
251
288
  // v5 — generateToken takes ONLY sessionId (Calls SDK has its own auth state
252
289
  // after CometChatCalls.login(); no authToken arg needed).
@@ -288,9 +325,11 @@ function endCall() {
288
325
 
289
326
  Skipping this leaves the camera light on until the tab is closed. Same canonical bug as iOS rule 1.5.
290
327
 
291
- ### 1.4 Server-minted auth tokens for production
328
+ ### 1.4 Calls login the DEFAULT path needs NONE; only `directCalling`/SDK-only do
292
329
 
293
- In v5 the Calls SDK has **its own login step**it no longer piggybacks on the Chat SDK's auth context implicitly. After `CometChat.login()` resolves on the chat side, call **`CometChatCalls.login(uid, apiKey)`** for dev or **`CometChatCalls.loginWithAuthToken(authToken)`** for production. The auth token is the same token your backend mints via the CometChat Create-Auth-Token API; the Calls SDK and Chat SDK accept it interchangeably.
330
+ > **For the common case additive ringing / default calling do NOT call `CometChatCalls.login`.** Install the calls SDK, let the call buttons appear automatically in `CometChatMessageHeader`, and mount `<CometChatIncomingCall />` once at the app root. That's the whole wiring. **Both canonical React v6 sample apps do calls this exact way with ZERO `CometChatCalls.login`/`CometChatCalls.init`** (verified: `cometchat-uikit-react-v6/sample-app/src/components/CometChatHome/CometChatHome.tsx:1740` mounts only `<CometChatIncomingCall />`; no `CometChatCalls.login` anywhere in either sample). The kit's default `defaultCalling` mode rides the Chat SDK's signaling adding a calls-login step here is needless plumbing, and an empty/wrong arg makes it **silently no-op**.
331
+
332
+ **`CometChatCalls.login` is required ONLY for** (a) `CallWorkflow.directCalling` (conference-style 1:1) or (b) the SDK-only / custom-WebRTC surface (§4c). In those cases — and only those — the v5 Calls SDK needs its own login: after `CometChat.login()` resolves on the chat side, call **`CometChatCalls.login(uid, apiKey)`** for dev or **`CometChatCalls.loginWithAuthToken(authToken)`** for production. The auth token is the same one your backend mints via the CometChat Create-Auth-Token API; the Calls SDK and Chat SDK accept it interchangeably.
294
333
 
295
334
  ```ts
296
335
  // Dev
@@ -300,8 +339,12 @@ await CometChatCalls.login(uid, import.meta.env.VITE_COMETCHAT_API_KEY);
300
339
  await CometChatCalls.loginWithAuthToken(authTokenFromBackend);
301
340
  ```
302
341
 
342
+ > **About `VITE_COMETCHAT_API_KEY`:** `CometChatCalls.login(uid, apiKey)` takes the app's **Auth Key** — the same value `cometchat-core` writes as `VITE_COMETCHAT_AUTH_KEY` (the env-prefix table establishes `APP_ID`/`REGION`/`AUTH_KEY`, not a separate `API_KEY`). In dev you can reuse `VITE_COMETCHAT_AUTH_KEY` here; if you prefer the `_API_KEY` name for readability, add it to your `.env` with the same Auth Key value. Don't leave it undefined — an empty arg makes the Calls login silently no-op (see the `directCalling` trap above).
343
+
303
344
  `cometchat-production` (web) covers the token-endpoint pattern.
304
345
 
346
+ > ⚠️ **`CallWorkflow.directCalling` silently fails without this login.** When you opt 1:1 calls into the conference-style UI by passing `callWorkflow={CallWorkflow.directCalling}` to `<CometChatCallButtons>` / `<CometChatOngoingCall>` etc., the kit routes through the Calls SDK directly and **requires `CometChatCalls.login()` to have completed**. Without it, calls **ring for ~2 seconds then drop with no error message** — the most painful failure mode in this skill. The UI Kit's default `defaultCalling` mode does NOT have this requirement (it uses the Chat SDK's signaling). Rule when emitting `directCalling`: always include the `CometChatCalls.login(...)` call alongside the Chat login above (ENG-35709).
347
+
305
348
  ### 1.5 Hangup cleanup — see rule 1.3
306
349
 
307
350
  ### 1.6 Permissions — `getUserMedia` prompts
@@ -328,6 +371,69 @@ There are no manifest-level permission declarations on web. HTTPS is required
328
371
 
329
372
  Mounting it inside a route component means it disappears on navigation — calls only ring on the screen where it's mounted. That's the canonical "calls don't work" bug on web.
330
373
 
374
+ ### 1.8 Init order — Chat init → Chat login → Calls init → Calls login (ENG-35708)
375
+
376
+ The order is load-bearing. Two crashes from real testers trace back to this:
377
+
378
+ - **`CometChatCalls.init` before `CometChat.login` → calls integration broke.** The Calls SDK reads context from the Chat SDK that only exists once a Chat session is established. Swapping init order silently fails or returns 401s on the first `generateToken`.
379
+ - **Crash on `Start Call` when only the Calls SDK was initialized.** No Chat SDK init at all → the ringing flow can't fire `initiateCall` because the Chat SDK isn't there.
380
+
381
+ **The only correct order in additive mode (chat + calls):**
382
+
383
+ ```
384
+ CometChat.init(appId, settings)
385
+ → CometChat.login(uid, authKey) // OR loginWithAuthToken(token)
386
+ → CometChatCalls.init({appId, region})
387
+ → CometChatCalls.login(uid, apiKey) // OR loginWithAuthToken(serverToken)
388
+ ```
389
+
390
+ In **standalone session-mode** (`product === "voice-video"`, no chat), use ONLY the Calls SDK — never call `CometChat.init` / `CometChat.login` at all. The kit's session-mode sample doesn't import the Chat SDK; matching that shape eliminates a class of "Chat init failed mid-meeting" failures.
391
+
392
+ ### 1.9 Don't double-up call buttons (ENG-35708)
393
+
394
+ Two testers reported call buttons appearing twice on the message screen. Cause: the kit's `<CometChatMessageHeader user={user} />` already renders `<CometChatCallButtons>` internally when a `user` prop is set (and the kit's default messages page mounts the header). Adding your own `<CometChatCallButtons user={user} />` next to either of those produces a duplicate set.
395
+
396
+ **Rule before emitting `<CometChatCallButtons>`:**
397
+
398
+ 1. Check whether the surrounding kit component already shows them. `CometChatMessageHeader` (any path that auto-renders the header) and the kit's default messages page include call buttons by default. (Note: there is no `CometChatConversationsWithMessages` composite in v6 — it was removed.)
399
+ 2. If yes, do NOT add a second `<CometChatCallButtons>`. To swap appearance or behavior, use the kit's `messageHeaderView` slot or set the relevant `hide*` flag instead of adding another instance.
400
+ 3. If no — you're on a custom screen that does not use those kit components — then `<CometChatCallButtons user={user} />` is appropriate. Mount it once, beside the user-info block.
401
+
402
+ ### 1.10 `CometChatOngoingCall` expects a `callSettingsBuilder`, NOT a built `CallSettings` (ENG-35708)
403
+
404
+ `CallSettingsBuilder` is not a bare export of either package — access it via the kit re-export: `import { CometChatUIKitCalls } from "@cometchat/chat-uikit-react"`, then `new CometChatUIKitCalls.CallSettingsBuilder()`. The prop shape is the **builder instance** (not the built settings object). The agent emitted:
405
+
406
+ ```tsx
407
+ // ✗ Wrong — TypeScript error on the prop type
408
+ const callSettings = new CometChatUIKitCalls.CallSettingsBuilder().enableDefaultLayout(true).build();
409
+ <CometChatOngoingCall callSettingsBuilder={callSettings} />
410
+ ```
411
+
412
+ The correct usage is:
413
+
414
+ ```tsx
415
+ // ✓ Right. Verified against the kit's CometChatOngoingCallProps (6.5.x):
416
+ // sessionID: string ← REQUIRED (non-optional) — omitting it TS-errors
417
+ // callSettingsBuilder?: ... ← OPTIONAL; the kit defaults to new CometChatUIKitCalls.CallSettingsBuilder()
418
+ // There is NO .setSessionID() on the builder — the session id is its OWN prop.
419
+ // The builder holds only configuration setters (enableDefaultLayout /
420
+ // setIsAudioOnlyCall / show*Button).
421
+ const callSettingsBuilder = new CometChatUIKitCalls.CallSettingsBuilder()
422
+ .enableDefaultLayout(true)
423
+ .setIsAudioOnlyCall(false);
424
+ <CometChatOngoingCall sessionID={sessionId} callSettingsBuilder={callSettingsBuilder} />
425
+ ```
426
+
427
+ > **Prefer the additive path over a manual `<CometChatOngoingCall>` mount.** Mounting `<CometChatIncomingCall />` at the app root and letting the kit drive the Outgoing → Ongoing transition needs no `sessionID` plumbing and is the build-clean, recommended approach (§1.x). Reach for a manual `<CometChatOngoingCall>` only when you're building a custom call screen — and then `sessionID` is mandatory.
428
+
429
+ Why this shape: the kit composes the builder with internal listeners (call-end, error, recording state) before calling `.build()`. Pre-building forecloses that composition. Pass the builder; let the kit build.
430
+
431
+ > ⚠️ **`callSettingsBuilder` is a different shape on different components** (verified vs the v6 React kit source — do not assume one form):
432
+ > - `<CometChatOngoingCall>` → a **builder instance** (`callSettingsBuilder={new CometChatUIKitCalls.CallSettingsBuilder()...}`), prop typed `typeof CometChatUIKitCalls.CallSettings`.
433
+ > - `<CometChatCallButtons>` → a **callback**: `callSettingsBuilder={(isAudioOnlyCall, user?, group?) => new CometChatUIKitCalls.CallSettingsBuilder()...}`.
434
+ > - `<CometChatIncomingCall>` (and Outgoing) → a **callback** taking the call: `callSettingsBuilder={(call) => new CometChatUIKitCalls.CallSettingsBuilder()...}`.
435
+ > All three are optional — omit the prop and the kit uses its own default builder (the simplest correct path). Only the OngoingCall form takes a bare instance; passing an instance where a callback is expected is a TS error.
436
+
331
437
  ---
332
438
 
333
439
  ## 2. Setup
@@ -380,7 +486,10 @@ export async function initCometChat() {
380
486
  export async function loginCometChat(uid: string) {
381
487
  await CometChat.login(uid, import.meta.env.VITE_COMETCHAT_AUTH_KEY);
382
488
 
383
- // v5 — Calls SDK login. Either form is fine; loginWithAuthToken is for production.
489
+ // v5 — Calls SDK login. Only needed for CallWorkflow.directCalling or the
490
+ // SDK-only/custom-WebRTC surface (see §1.4) — for the COMMON additive/default
491
+ // ringing path you can OMIT this whole block (the kit rides the Chat SDK's
492
+ // signaling). Shown here for completeness; harmless when included with a valid key.
384
493
  if (!CometChatCalls.getLoggedInUser()) {
385
494
  await CometChatCalls.login(uid, import.meta.env.VITE_COMETCHAT_API_KEY);
386
495
  // OR: await CometChatCalls.loginWithAuthToken(serverMintedToken);
@@ -390,6 +499,8 @@ export async function loginCometChat(uid: string) {
390
499
 
391
500
  The module-level `initialized` flag prevents StrictMode double-init in React 18+ dev mode. The `getLoggedInUser()` guard prevents re-login on hot reload.
392
501
 
502
+ > ⚠️ **Additive mode: the chat layer must init via `CometChatUIKit.init()`, not raw `CometChat.init()`.** The example above shows `CometChat.init()` for the SDK-only path. But when you use the kit's call components (`<CometChatCallButtons>` / `<CometChatIncomingCall>` / `<CometChatOngoingCall>`), they read `uiKitSettings` that **only `CometChatUIKit.init(new UIKitSettingsBuilder()…build())` sets** — your `cometchat-core` setup already does this. Initializing the chat layer with raw `CometChat.init()` instead leaves the components logging **`uiKitSettings not available`** (non-fatal — calls still connect — but a real DX smell). In additive mode, keep `CometChatUIKit.init()` as your chat init and have this calls module ADD only `CometChatCalls.init()` + `CometChatCalls.login()` on top. *(Verified by a two-user live call smoke 2026-06-04: with `CometChatUIKit.init()` the ring→accept→join flow runs with zero console errors; with raw `CometChat.init()` both sides log the warning.)*
503
+
393
504
  ### Framework-specific env prefixes (already covered by `cometchat-core`)
394
505
 
395
506
  | Framework | Env prefix |
@@ -464,7 +575,7 @@ When `product === "voice-video"` and there is no existing chat UI integration.
464
575
 
465
576
  ### 4a. Standalone — Session mode (meeting-room UX, no ringing)
466
577
 
467
- Calls SDK ONLY. NO Chat SDK. Matches the upstream sample at `~/Downloads/calls-sdk/calls-sdk-javascript-5/sample-apps/cometchat-calls-sample-app-react/`. The skill scaffolds:
578
+ Calls SDK ONLY. NO Chat SDK. Matches the upstream sample at `calls-sdk-javascript-5/sample-apps/cometchat-calls-sample-app-react/`. The skill scaffolds:
468
579
 
469
580
  1. **`cometchat/init.ts`** — `CometChatCalls.init({ appId, region, authKey })` ONLY. No `CometChat.init`, no `CometChat.login`. Pass `authKey` at init time so subsequent `CometChatCalls.login(uid)` calls need no second arg.
470
581
  2. **`cometchat/CometChatProvider.tsx`** — Runs Calls SDK init on mount, exposes `loggedInUser` via `CometChatCalls.getLoggedInUser()`, gates children on success.
@@ -487,6 +598,104 @@ Dual-SDK: Chat SDK signaling channel + Calls SDK media channel. The skill scaffo
487
598
  7. **Optional Web Push** — Service Worker registration + push subscription endpoint, if the user opts in.
488
599
  8. **HTTPS check** — warns if dev server is HTTP non-localhost.
489
600
 
601
+ ### 4c. SDK-only — without any UI Kit call components (ENG-35707)
602
+
603
+ When the user wants to build their own call UI (custom controls, a custom in-call screen) but still wants ringing semantics, they're on the SDK-only path: Chat SDK for signaling + Calls SDK for media, NO `<CometChatCallButtons>` / `<CometChatOngoingCall>` / `<CometChatIncomingCall>` from the UI Kit. The previous version of this skill was UI-Kit-first and these gotchas were silent. Cover them explicitly when you scaffold this shape.
604
+
605
+ #### Constants — two enums, same meaning, easy to confuse
606
+
607
+ | Constant | Source | Use it for |
608
+ |---|---|---|
609
+ | `CometChat.CALL_TYPE.AUDIO` / `.VIDEO` | `@cometchat/chat-sdk-javascript` | The **Chat SDK** call entity — passed to `new CometChat.Call(receiver, callType, receiverType)` and to `CometChat.initiateCall`. |
610
+ | `CometChat.RECEIVER_TYPE.USER` / `.GROUP` | `@cometchat/chat-sdk-javascript` | The **Chat SDK** call entity — passed alongside `callType`. |
611
+ | `CometChatCalls.constants.TYPE.VOICE` / `.VIDEO` | `@cometchat/calls-sdk-javascript` | The **Calls SDK** session-type enum. Matches the `SessionSettings` `sessionType` value (`'VOICE'` / `'VIDEO'`). |
612
+
613
+ These are NOT interchangeable. `CometChat.CALL_TYPE.AUDIO` (Chat SDK) ≠ `CometChatCalls.constants.TYPE.VOICE` (Calls SDK) even though they mean the same thing. Use the Chat SDK enum on the `Call` entity you pass to `initiateCall`; use the Calls SDK enum on `SessionSettings.sessionType`.
614
+
615
+ > Note: `CallSettingsBuilder` has **no** `setCallType(...)` method — that lives on `CallLogRequestBuilder` (and takes `'video' | 'audio'` for filtering call logs). The audio knob for a session is `CallSettingsBuilder().setIsAudioOnlyCall(true)`, or `sessionType: 'VOICE'` in the `SessionSettings` object form. (Verified against the calls-sdk `index.d.ts`.)
616
+
617
+ #### Audio-only calls — `setIsAudioOnlyCall(true)` on `CallSettingsBuilder`
618
+
619
+ The audio-only knob lives on the Calls SDK's `CallSettingsBuilder`, not on the Chat SDK call entity. You set the Chat SDK call type to `AUDIO` for the ringing/signaling channel, and then ALSO set `setIsAudioOnlyCall(true)` on the call settings used for `joinSession`:
620
+
621
+ ```typescript
622
+ // joinSession's 2nd arg is a SessionSettings OBJECT (NOT the output of
623
+ // CallSettingsBuilder.build() — that's a CallSettings, accepted only by the
624
+ // deprecated startSession). The session is carried by the `token` (from
625
+ // generateToken(sessionId)); there is no sessionId/setSessionID in the settings.
626
+ // Voice-only: set sessionType: 'VOICE' (the object equivalent of the v4
627
+ // builder's setIsAudioOnlyCall(true)).
628
+ const settings = { sessionType: 'VOICE' };
629
+
630
+ const result = await CometChatCalls.joinSession(token, settings, containerRef.current);
631
+ ```
632
+
633
+ Without `sessionType: 'VOICE'`, voice calls still acquire the camera (it's just not rendered) — which trips the browser permission prompt and lights the camera indicator. Always pair `CALL_TYPE.AUDIO` (Chat) + `sessionType: 'VOICE'` in the join settings (Calls) for voice calls.
634
+
635
+ #### Container-mount timing — `joinSession` MUST fire after the container is in the DOM
636
+
637
+ This is the most painful SDK-only failure mode. The natural site to call `joinSession` is the call-listener event `onOutgoingCallAccepted` (caller side) or `onIncomingCallReceived` → user-accepts (receiver side). But those events fire BEFORE your in-call panel has rendered — the container `<div ref={containerRef}>` is still `null`. `joinSession(token, settings, null)` throws `Container dimensions and number of tiles must be positive` (or silently no-ops in some kit versions).
638
+
639
+ **Pattern: drive the container via state and join in a `useEffect` that depends on both the call state AND the container ref.**
640
+
641
+ ```tsx
642
+ function CallScreen() {
643
+ const [phase, setPhase] = useState<"idle" | "joining" | "in-call">("idle");
644
+ const [callToken, setCallToken] = useState<string | null>(null);
645
+ const containerRef = useRef<HTMLDivElement>(null);
646
+
647
+ // Step 1: register call listeners
648
+ useEffect(() => {
649
+ const listenerID = "call-screen-" + Date.now();
650
+ CometChat.addCallListener(listenerID, new CometChat.CallListener({
651
+ onOutgoingCallAccepted: async (call: any) => {
652
+ // DO NOT call joinSession here — the container ref is still null.
653
+ // Just flip the phase and let the effect below handle it.
654
+ const tokenRes = await CometChatCalls.generateToken(call.getSessionId(), authToken);
655
+ setCallToken(tokenRes.token);
656
+ setPhase("in-call");
657
+ },
658
+ onIncomingCallReceived: (call: any) => { /* show your accept UI */ },
659
+ }));
660
+ return () => CometChat.removeCallListener(listenerID);
661
+ }, []);
662
+
663
+ // Step 2: when phase flips to "in-call" AND container is mounted, join
664
+ useEffect(() => {
665
+ if (phase !== "in-call" || !callToken || !containerRef.current) return;
666
+ const container = containerRef.current;
667
+ if (container.clientWidth === 0 || container.clientHeight === 0) return; // not laid out yet
668
+ // session is carried by callToken (from generateToken). joinSession takes a
669
+ // SessionSettings OBJECT — {} uses the default layout. (Do NOT pass
670
+ // CallSettingsBuilder.build() here — that CallSettings type is for the
671
+ // deprecated startSession, and is incompatible with joinSession.)
672
+ CometChatCalls.joinSession(callToken, {}, container);
673
+ }, [phase, callToken]);
674
+
675
+ return (
676
+ <>
677
+ {phase === "in-call" && (
678
+ <div ref={containerRef} style={{ position: "fixed", inset: 0, width: "100vw", height: "100vh" }} />
679
+ )}
680
+ </>
681
+ );
682
+ }
683
+ ```
684
+
685
+ The key idea: the call-listener handler doesn't call `joinSession` directly. It updates state. The effect that depends on `phase` AND the ref runs ONLY after React has committed the container `<div>` to the DOM. This is the same race as "modal `<dialog>` mounted before `showModal()`" — it's a React/DOM-timing issue, not a SDK bug.
686
+
687
+ #### Group calls vs 1:1 calls — defaults differ
688
+
689
+ - **1:1 calls** use the ringing pattern: `new CometChat.Call(receiverUid, CALL_TYPE.VIDEO, RECEIVER_TYPE.USER)` → `CometChat.initiateCall(call)` → receiver gets `onIncomingCallReceived`. Default call type for a 1:1 video chat is video; for audio chat, audio.
690
+ - **Group calls** in the UI Kit go through a **custom-message broadcast** (`CometChatCallButtons` sends `CustomMessage type="meeting"`), not `initiateCall`. SDK-only groups: send your own custom message + `CometChatCalls.joinSession` with a shared sessionId — there is no "ring a group" primitive.
691
+ - **Group call default is voice** in the kit's `CometChatCallButtons` for groups; 1:1 default is video. If you're building custom buttons, replicate this — group calls are usually meeting-style (voice + screen share); 1:1s are usually video.
692
+
693
+ Cross-reference: `cometchat-native-calls` §3 documents the same group-call custom-message pattern for React Native (memory: [[project_group_calls_kit_semantic]]).
694
+
695
+ #### Container CSS — non-zero dimensions before `joinSession`
696
+
697
+ Already covered in the §⚠️ "Call container — must have non-zero dimensions" callout at the top, but it bears repeating in the SDK-only flow because there's no UI Kit component wrapping the container. Inline-render the container with `position: fixed; inset: 0; width: 100vw; height: 100vh` (full-screen overlay) OR `display: flex; flex: 1; min-height: 600px` (embedded). NEVER `display: none` + toggle — the container measures zero while hidden and `joinSession` throws.
698
+
490
699
  ## 5. Additive integration
491
700
 
492
701
  When `cometchat-core` integration already exists. The skill:
@@ -532,6 +741,7 @@ When `cometchat-core` integration already exists. The skill:
532
741
 
533
742
  ## 8. Pointers
534
743
 
744
+ - `references/virtual-background.md` — blur / custom image / clear (web-only; native iOS/Android don't support it)
535
745
  - `cometchat-core` — provider pattern, init guard, login order
536
746
  - `cometchat-components` — full UI Kit catalog (additive mode)
537
747
  - `cometchat-{nextjs,react,react-router,astro}-patterns` — framework-specific SSR guards, route placement
@@ -74,7 +74,8 @@ Wherever you call `CometChat.login(uid, authKey)` (or your auth-token equivalent
74
74
  ```ts
75
75
  const user = await CometChat.login(uid, authKey);
76
76
  const authToken = user.getAuthToken();
77
- await CometChatCalls.login(authToken);
77
+ // CometChatCalls.login(uid, authKey?) takes a UID — pass a token via loginWithAuthToken.
78
+ await CometChatCalls.loginWithAuthToken(authToken);
78
79
  ```
79
80
 
80
81
  If you use server-minted auth tokens (production hygiene — see `cometchat-production`), the same auth token works for both SDKs.
@@ -121,11 +122,11 @@ If you want a custom call experience instead of the kit's default UI, see `comet
121
122
 
122
123
  - [ ] `@cometchat/calls-sdk-javascript@^5` in package.json
123
124
  - [ ] Calls SDK init runs AFTER chat SDK init
124
- - [ ] `CometChatCalls.login(authToken)` runs AFTER `CometChat.login`
125
+ - [ ] `CometChatCalls.loginWithAuthToken(authToken)` runs AFTER `CometChat.login`
125
126
  - [ ] `CometChatIncomingCall` mounted at app root
126
127
  - [ ] Call buttons visible in CometChatMessageHeader
127
128
  - [ ] Run `cometchat verify --calls` — should pass all 20 checks
128
- - [ ] Smoke test: 2 tabs (different users), call from one, ringing in the other
129
+ - [ ] Smoke test: **two ISOLATED browser contexts** (normal + Incognito window, or two browsers/devices — NOT two tabs of one browser; the Chat SDK shares one session per origin), call from one, ringing in the other
129
130
 
130
131
  ---
131
132
 
@@ -85,10 +85,9 @@ useEffect(() => {
85
85
  const handler = (newLayout: string) => {
86
86
  setLayout(newLayout as typeof layout);
87
87
  };
88
- CometChatCalls.addEventListener("onCallLayoutChanged", handler);
89
- return () => {
90
- CometChatCalls.removeEventListener("onCallLayoutChanged", handler);
91
- };
88
+ // addEventListener returns an unsubscribe fn — there is no removeEventListener.
89
+ const off = CometChatCalls.addEventListener("onCallLayoutChanged", handler);
90
+ return () => off();
92
91
  }, []);
93
92
  ```
94
93
 
@@ -138,7 +137,7 @@ For general meetings: don't lock. Let users pick.
138
137
  1. **Calling `setLayout` before `joinSession` resolves.** Throws — the call surface isn't bound yet. Set the initial layout via `callSettings.layout` instead.
139
138
  2. **Storing layout in URL or shared state.** Layout is per-participant local. Sharing it via URL/Firestore causes layout flicker as multiple peers fight to set it.
140
139
  3. **String literals everywhere.** Use `CometChatCalls.constants.LAYOUT` so typos surface at autocomplete time, not runtime.
141
- 4. **Forgetting `removeEventListener` on unmount.** Listener accumulates across calls → `setLayout` fires N times.
140
+ 4. **Forgetting to call the unsubscribe fn on unmount.** `addEventListener` returns a `() => void` — call it in cleanup (there is no `removeEventListener`). Otherwise the listener accumulates across calls → `setLayout` fires N times.
142
141
  5. **Custom switcher AND kit's switcher both visible.** Confusing. Set `hideChangeLayoutButton: true` if you ship your own.
143
142
 
144
143
  ---
@@ -156,6 +155,6 @@ For general meetings: don't lock. Let users pick.
156
155
  ## Pointers
157
156
 
158
157
  - `cometchat-react-calls/SKILL.md` — call surface architecture
159
- - `cometchat-react-calls/references/recording.md` — sister cross-cutting concern
158
+ - `cometchat-react-calls/references/recording-screen-share.md` — sister cross-cutting concern
160
159
  - `cometchat-react-calls/references/in-call-chat.md` — chat panel sits beside layout
161
160
  - Canonical docs: https://www.cometchat.com/docs/calls/javascript/call-layouts
@@ -71,7 +71,7 @@ Each user calls this with the SAME `sessionId` but gets a token tied to their ow
71
71
 
72
72
  ## Join session
73
73
 
74
- This pattern mirrors the upstream sample exactly: `/Users/swapnil/Downloads/calls-sdk/calls-sdk-javascript-5/sample-apps/cometchat-calls-sample-app-react/src/pages/join-session/JoinSession.tsx`. Customer-validated against the v5 SDK as the known-good shape.
74
+ This pattern mirrors the upstream sample exactly: `calls-sdk-javascript-5/sample-apps/cometchat-calls-sample-app-react/src/pages/join-session/JoinSession.tsx`. Customer-validated against the v5 SDK as the known-good shape.
75
75
 
76
76
  ```tsx
77
77
  import { useEffect, useRef, useState } from "react";
@@ -3,7 +3,9 @@
3
3
  When the kit's default `<CometChatOngoingCall />` doesn't fit your app's design system, drop down to the Calls SDK directly. Two escalation paths:
4
4
 
5
5
  1. **Style the kit's component** — pass style props / CSS variable overrides. Cheapest. Covers most cases.
6
- 2. **Build your own surface on the SDK** — use `CometChatCalls.joinSession(token, settings, container)` directly with your own DOM container. Maximum control. The kit doesn't render anything; you do. (`startSession` is a deprecated v4 shim — use `joinSession`.)
6
+ 2. **Build your own surface on the SDK** — drive the session directly with your own DOM container. Maximum control. The kit doesn't render anything; you do.
7
+
8
+ > ⚠️ **Two join APIs — pick by which settings type you build.** `joinSession(token, sessionSettings, container)` is the v5 canonical and takes a **`SessionSettings` object** (the `hide*` / `sessionType` / `layout` flags). It does **not** accept the output of `CallSettingsBuilder.build()` — those are incompatible types. The `CallSettingsBuilder` (with `enableDefaultLayout(false)`, `setCallListener`, etc.) produces a `CallSettings` consumed only by the **deprecated** `startSession(token, callSettings, container)`. So: **hybrid / hide-chrome custom UI → object + `joinSession`** (preferred); **fully-custom render-your-own-tiles (`enableDefaultLayout(false)`) → builder + `startSession`** (the one path where the deprecated call is still required, because `enableDefaultLayout` lives only on the builder).
7
9
 
8
10
  This reference covers path 2 — full custom UI on the SDK. Path 1 is in the kit's component documentation (see `cometchat-customization`).
9
11
 
@@ -47,6 +49,8 @@ export function CustomOngoingCallView({ sessionId, authToken, onCallEnded }: Pro
47
49
  const remoteVideoRef = useRef<HTMLVideoElement>(null);
48
50
 
49
51
  useEffect(() => {
52
+ // ⚠️ CometChatCalls.OngoingCallListener is @deprecated (use addEventListener).
53
+ // It's only here because enableDefaultLayout(false) + startSession require it.
50
54
  const callListener = new CometChatCalls.OngoingCallListener({
51
55
  onUserListUpdated: (userList: unknown) => {
52
56
  // userList = current participants — re-render your custom roster
@@ -62,9 +66,6 @@ export function CustomOngoingCallView({ sessionId, authToken, onCallEnded }: Pro
62
66
  onError: (error: unknown) => {
63
67
  console.error("Call error:", error);
64
68
  },
65
- onAudioModesUpdated: (audioModes: unknown[]) => {
66
- // available mic / speaker devices
67
- },
68
69
  onCallSwitchedToVideo: (call: unknown) => {
69
70
  // remote upgraded the call from voice to video
70
71
  },
@@ -73,11 +74,15 @@ export function CustomOngoingCallView({ sessionId, authToken, onCallEnded }: Pro
73
74
  },
74
75
  });
75
76
 
77
+ // ⚠️ CallSettingsBuilder method names (verified against calls-sdk-javascript@5):
78
+ // - there is NO .setSessionID() on the builder — sessionId flows through
79
+ // generateToken(sessionId) below, NOT the builder
80
+ // - it's .setIsAudioOnlyCall(bool), not .setIsAudioOnly()
81
+ // - it's .setCallListener(listener), not .setCallEventListener()
76
82
  const settings = new CometChatCalls.CallSettingsBuilder()
77
- .setSessionID(sessionId)
78
- .setIsAudioOnly(false)
83
+ .setIsAudioOnlyCall(false)
79
84
  .enableDefaultLayout(false) // ← key: we render the UI ourselves
80
- .setCallEventListener(callListener)
85
+ .setCallListener(callListener)
81
86
  .build();
82
87
 
83
88
  // v5 generateToken takes ONLY sessionId — authToken is internal after CometChatCalls.login().
@@ -86,8 +91,11 @@ export function CustomOngoingCallView({ sessionId, authToken, onCallEnded }: Pro
86
91
  // With custom UI you typically render your own <video> elements; the
87
92
  // container can be hidden but must still be a real DOM node.
88
93
  const container = document.getElementById("calls-container")!;
89
- // joinSession is the v5 canonical startSession is a deprecated shim.
90
- CometChatCalls.joinSession(tokenRes.token, settings, container);
94
+ // This example builds CallSettings via CallSettingsBuilder (enableDefaultLayout(false)),
95
+ // so it MUST use startSession — joinSession only accepts a SessionSettings object,
96
+ // not the builder's CallSettings output. startSession is deprecated but is the only
97
+ // consumer of enableDefaultLayout(false)-style fully-custom settings.
98
+ CometChatCalls.startSession(tokenRes.token, settings, container);
91
99
  });
92
100
 
93
101
  return () => cleanup();
@@ -105,10 +113,10 @@ export function CustomOngoingCallView({ sessionId, authToken, onCallEnded }: Pro
105
113
  <video ref={remoteVideoRef} autoPlay playsInline className="remote-tile" />
106
114
  <video ref={localVideoRef} autoPlay playsInline muted className="local-tile" />
107
115
  <ControlPanel
108
- onMute={() => CometChatCalls.muteAudio(true)}
109
- onUnmute={() => CometChatCalls.muteAudio(false)}
110
- onCameraOff={() => CometChatCalls.pauseVideo(true)}
111
- onCameraOn={() => CometChatCalls.pauseVideo(false)}
116
+ onMute={() => CometChatCalls.muteAudio()}
117
+ onUnmute={() => CometChatCalls.unmuteAudio()}
118
+ onCameraOff={() => CometChatCalls.pauseVideo()}
119
+ onCameraOn={() => CometChatCalls.resumeVideo()}
112
120
  onSwitchCamera={() => CometChatCalls.switchCamera()}
113
121
  onEnd={() => {
114
122
  CometChatCalls.leaveSession();
@@ -151,7 +159,45 @@ function ControlPanel(props: {
151
159
  }
152
160
  ```
153
161
 
154
- The SDK methods (`muteAudio`, `pauseVideo`, `switchCamera`) propagate to all participants via the SDK's signaling — you don't manage track state yourself.
162
+ The SDK methods (`muteAudio`/`unmuteAudio`, `pauseVideo`/`resumeVideo`, `switchCamera`) propagate to all participants via the SDK's signaling — you don't manage track state yourself.
163
+
164
+ > ⚠️ **These are no-argument methods.** `muteAudio(): void` / `pauseVideo(): void` — there is NO boolean parameter. `CometChatCalls.muteAudio(false)` does **not** unmute (the arg is ignored — it still mutes). Use the explicit pair: `muteAudio()` / `unmuteAudio()` and `pauseVideo()` / `resumeVideo()`. (There is **no** `toggleAudio()` / `toggleVideo()` in the v5 SDK — track the muted/paused state yourself and call the matching method of the pair.)
165
+
166
+ > ⚠️ **Optimistic local state desyncs.** A control panel that only flips its own `useState` on click (as the example above does) will show a stale label whenever mute/camera/screen-share change from *outside* your bar — a join-muted call (`startAudioMuted`), the browser's own "Stop sharing" button, or another surface. Reconcile by subscribing to the SDK's media events and driving state from them: `onAudioMuted` / `onAudioUnMuted` / `onVideoPaused` / `onVideoResumed` / `onScreenShareStarted` / `onScreenShareStopped` / `onRecordingStarted` / `onRecordingStopped`. Seed the initial state from your join options so the first render is correct too.
167
+
168
+ ---
169
+
170
+ ## Two custom-panel models — and the `hideHeaderPanel` footgun
171
+
172
+ There are **two** ways to put your own controls on a call, and they are very different:
173
+
174
+ **Model A — fully custom (`enableDefaultLayout(false)`).** The SDK draws nothing; you render every tile, every button, the whole surface. That's the path above. It leans on **two deprecated V5 APIs** — `startSession` (the only consumer of builder-produced `CallSettings`) and the `CometChatCalls.OngoingCallListener` accessor (the SDK marks it `@deprecated → use addEventListener`) — because `enableDefaultLayout(false)` exists only on the builder and has no `SessionSettings`-object equivalent. Use it only when you truly must render your own video tiles, and accept owning a11y, recording/screen-share plumbing, and the eventual migration off these shims. **For everything else, prefer Model B — it's 100% current V5 (`joinSession` + object + `addEventListener`).**
175
+
176
+ **Model B — hybrid (keep the SDK layout, replace only the bottom bar).** Far cheaper and far more common. You keep the SDK's default layout but pass `SessionSettings` flags to `joinSession` to hide just the control bar, then render your own bar over it:
177
+
178
+ ```ts
179
+ const settings = {
180
+ sessionType: 'VIDEO',
181
+ layout: 'TILE',
182
+ hideControlPanel: true, // ← hide ONLY the bottom control bar; render your own
183
+ // hideHeaderPanel: true, // ← ⚠️ DO NOT add this unless you mean it (see below)
184
+ };
185
+ await CometChatCalls.joinSession(token, settings, container);
186
+ ```
187
+
188
+ > ⚠️ **`hideHeaderPanel: true` silently disables Virtual Background, In-Call Chat, and the Participant List.** Those three features live in the SDK's **header** panel, not the control bar. If you set `hideHeaderPanel: true` to "clean up" a custom-bar call, you remove them with no replacement — and there are **no plain `CometChatCalls` static methods** to rebuild VB or in-call chat in your own bar (VB is exposed only as call-session instance methods / action constants like `setBackgroundBlur`, not statics). So a custom *control* bar should hide only `hideControlPanel`; leave `hideHeaderPanel` false so VB / chat / participant-list stay reachable. Real customer bug, 2026-06: ticking a "custom control panel" option flipped both flags and made VB + chat vanish.
189
+
190
+ If you genuinely don't want the header either, you're back in Model A territory — own those features yourself.
191
+
192
+ ### Participant count from a custom bar
193
+
194
+ Don't derive the roster from `onParticipantJoined` / `onParticipantLeft` increments — those fire only for participants who join/leave **after** you, so a counter seeded at 0 (or 1) **undercounts when you join a call already in progress**. Subscribe to the authoritative full-list event instead:
195
+
196
+ ```ts
197
+ CometChatCalls.addEventListener('onParticipantListChanged', (list) =>
198
+ setParticipants(Math.max(1, list.length)), // list includes the local user
199
+ );
200
+ ```
155
201
 
156
202
  ---
157
203
 
@@ -185,7 +231,7 @@ Once `startSession` runs, the SDK takes over the camera/mic — release your pre
185
231
 
186
232
  The Calls SDK is layout-agnostic when `enableDefaultLayout(false)`. You compose remote tiles in any CSS layout:
187
233
 
188
- - **Spotlight** — one large remote tile + small thumbnails for others. Track which user is speaking (`onActiveSpeakerUpdated` event in some SDK builds) and swap the spotlight.
234
+ - **Spotlight** — one large remote tile + small thumbnails for others. Track who's speaking via the `onDominantSpeakerChanged` event (NOT `onActiveSpeakerUpdated` that name doesn't exist) and swap the spotlight.
189
235
  - **Grid** — CSS grid with auto-fit columns, 1-N participant tiles equally sized.
190
236
  - **Picture-in-picture** — small floating remote video that survives navigation. Mount it in a portal at the layout root (similar to `<CometChatIncomingCall />`).
191
237