cometchat-flutter-v6-core
SkillMediaAdd CometChat chat to a Flutter app end-to-end — detect the project, get & verify dashboard credentials, init→login→render, and the drop-in conversation UI. The core knowledge every other Flutter v6 skill builds on. Triggers: 'add chat to my flutter app', 'integrate cometchat flutter', 'set up cometchat credentials flutter', 'show conversations and messages in flutter'.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the cometchat-flutter-v6-core skill
What this skill tells your AI
The instructions your AI receives, as published by cometchat/cometchat-skills in skills/cometchat-flutter-v6-core/SKILL.md and read by ahel’s review.
Ground truth:
cometchat_chat_uikit@6(6.1.0) +cometchat_sdk@^5.0.6. EveryCometChat*symbol here is incatalogs/flutter-v6.json— compiler-verified against the published package. Signatures marked [verified] were compiled because the docs were wrong, or (forinitFromSettings) deliberately silent (DOCS-BACKLOG.mdPART 4): trust this file for those, fetch the rest viareferences/docs-map.md. THIN map loaded every run; depth inreferences/*.
Use this skill when
"add chat to my Flutter app", "integrate CometChat in Flutter", "set up CometChat credentials", "show a conversations + messages screen". An unscoped "add chat" means a production-ready core surface — a CometChatConversations screen pushing a message screen, with threaded replies and search wired, in Scaffold/SafeArea, keyboard-safe, every screen popping back — NOT a two-widget demo, NOT the whole tab-based app (see the golden path). It grows on request → cometchat-flutter-v6-placement.
Install
flutter pub add cometchat_chat_uikit
Pin the major in pubspec.yaml — cometchat_chat_uikit: ^6.1.0 (a bare any can resolve across majors). The Chat SDK (cometchat_sdk) comes transitively and is re-exported by the kit barrel — do NOT add it separately unless you import SDK-only paths. Voice/video calling = a settings flag + native config (cometchat_calls_sdk is already a transitive kit dependency — see below) → cometchat-flutter-v6-calls.
Platform minimums — Android minSdk = 26 in android/app/build.gradle.kts; iOS platform :ios, '15.1' in ios/Podfile. The getting-started page says 24 / 13.0 and both are too low (DOCS-BACKLOG D7). The kit's own AAR allows 21, but transitive deps set the real floor and this one is not optional: cometchat_chat_uikit depends on cometchat_calls_sdk unconditionally — it sits in the main dependencies: block — and that package pins minSdkVersion 26 / platform :ios, '15.1' (5.0.7). Gradle and CocoaPods take the maximum across the graph, so a lower value is a build error whether or not the app uses calling.
Setup & credentials (essentials — full detail: references/setup-credentials.md)
- Detect by READING the repo —
pubspec.yaml+ lockfile (deps and the kit major),lib/main.dart, state management, navigation, and how config is handled. Reuse an existing.cometchat/config.jsonor settings asset (skip re-setup). Signal table:references/setup-credentials.md. - version_conflict — STOP if the project already has
cometchat_chat_uikitv5 (or any non-v6 major); reconcile first, never mix majors (RULES.md). A v5 project that wants v6 →cometchat-flutter-v6-migration. - Credentials — OFFER the dashboard fetch FIRST; never default to "paste it yourself." When App ID / Region / Auth Key are missing, offer (a) fetch from your dashboard (recommended) — load the CLI on demand, pick an EXISTING app (never auto-create) — or (b) manual paste. Then the SKILL writes
cometchat-settings.json(§4) from those creds; the CLI is dashboard/API-only and never writes Dart (RULES.md§21). Never defer credentials to a "add them yourself" TODO. Exact commands + the app-picker flow:references/setup-credentials.md. - Write the settings asset + register it — commit only a placeholder (no real Auth Key) and do not gitignore it (a registered asset must exist or a fresh-clone
flutter buildfails — see the note in §Integration ordering); never echo the Auth Key. Prod → server-minted auth token, not the Auth Key. - Authorize =
initthenloginboth hitonSuccess. An auth error is almost always the wrong Region.
Integration ordering (BAKED — invariant; docs: init must complete before login, login before any widget)
initFromSettings() once at startup → login(UID) after init succeeds → only THEN render any CometChat* widget.
Init via initFromSettings — the file-based, telemetry-attributed path (RULES.md §5). It reads a cometchat-settings.json asset and persists integrationSource="ai-agent". Flutter's signature takes NO settings argument (unlike web, which passes a settings object) — the file IS the input:
// [verified vs 6.1.0] — INTENTIONALLY undocumented upstream (@nodoc, owner decision:
// DOCS-BACKLOG F4 WONTFIX). Prefer it over the docs' UIKitSettingsBuilder + init()
// path, which loses telemetry attribution. The shape below is the contract.
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
await CometChatUIKit.initFromSettings(
onSuccess: (String message) => debugPrint('CometChat initialized'),
onError: (CometChatException e) => debugPrint('Init failed: ${e.message}'),
);
cometchat-settings.json at the project root, registered in pubspec.yaml under flutter: assets::
{
"appId": "APP_ID",
"region": "REGION",
"credentials": { "authKey": "AUTH_KEY" },
"uiKit": { "subscribePresenceForAllUsers": true, "enableCalling": false },
"chatSDK": { "autoEstablishSocketConnection": true }
}
Keys are read exactly as above.
uiKit.enableCallingis the only way to turn calling on via this path (UIKitSettingsdefaults it to false) — leave itfalseuntil the user asks for calls.credentials.authKeyis dev-only; omit it for production and log in with a server-minted token. Make a fresh clone build. A file registered underflutter: assets:MUST exist at build time orflutter build bundlefails with "No file or variants found for asset: cometchat-settings.json." So do not gitignore the registered asset. Instead commit a placeholdercometchat-settings.json— same shape, with a placeholder/emptyauthKey(NEVER a real dev Auth Key) — and have each developer and CI overwrite it locally/at build time with real credentials. (Enforce "no real key committed" via a pre-commit check or CI, not.gitignore.) For production, CI generates the prod-flavoured file (no Auth Key) at build time (cometchat-flutter-v6-production).
// login AFTER init succeeds. CometChatUIKit.login already checks getLoggedInUser()
// internally and no-ops if that UID is signed in, so no host-side re-login guard is needed.
await CometChatUIKit.login(
uid,
onSuccess: (User user) => debugPrint('Logged in: ${user.name}'),
onError: (CometChatException e) => debugPrint('Login failed: ${e.message}'),
);
Which UID?
login()needs a user that ALREADY EXISTS — never invent one. ASK, or take one from Dashboard → Users; fresh apps seedcometchat-uid-1…. The only tentative suggestion iscometchat-uid-1, labelled "if this is a fresh app." Prod →CometChatUIKit.loginWithAuthToken(authToken, …)with a token minted server-side. Init-once, hot-restart, and gating the first frame:references/lifecycle.md.
Widget / API map (BAKED closed list — from the catalog)
Init/session: CometChatUIKit (initFromSettings · login · loginWithAuthToken · logout · loggedInUser), UIKitSettingsBuilder, CometChatSubscriptionType, CometChatException.
Core surface: CometChatConversations, CometChatMessageHeader, CometChatMessageList, CometChatMessageComposer; wired affordances CometChatThreadedHeader, CometChatSearch.
Grow set (added on request): CometChatUsers, CometChatGroups, CometChatGroupMembers, CometChatChangeScope, CometChatCallLogs. Incoming calls need NO widget — with calling on, the kit presents the overlay itself (-calls).
TWO BARRELS — a real compile trap.
package:cometchat_chat_uikit/cometchat_chat_uikit.dartgives you the chat widgets and the re-exported Chat SDK (User,Group,Conversation,BaseMessage,TextMessage— no separate import). Every calls symbol (CometChatIncomingCall,CometChatOutgoingCall,CometChatCallButtons,CometChatCallLogs,CometChatCallBubble,CometChatCalls) lives ONLY inpackage:cometchat_chat_uikit/cometchat_calls_uikit.dart, and that barrel does NOT re-export the chat widgets — a calls screen imports both. Verified: usingCometChatIncomingCallwith only the chat import fails to compile. The v6 widget isCometChatThreadedHeader—CometChatThreadHeader(the React name) does NOT exist here. Never carry a name across families.
Hot-path props (BAKED — the golden path needs NO fetch)
CometChatConversations:onItemTap(Conversation)(select → push the message screen) ·hideSearch·searchReadOnly(settrueso the field acts as a button) ·onSearchTap(→ pushCometChatSearch) ·conversationsRequestBuilder(scope touser/groupwhen the ask is DM-only or groups-only — reuse the builder, don't client-filter) ·hideAppbar·appBarOptions·onBack.CometChatMessageHeader:user:/group:(pass the SAME target as the list) ·showBackButton(defaulttrue) +onBack·hideVoiceCallButton/hideVideoCallButton(call buttons are built in — leave them unless calls are out of scope) ·auxiliaryButtonView/trailingView(where a custom action goes — see search below).CometChatMessageList:user:/group:·parentMessageId(thread mode) ·onThreadRepliesClick[verified] — the type isThreadRepliesClick = void Function(BaseMessage message, BuildContext context, {CometChatMessageTemplate? template}); a one-argument closure does not compile (DOCS-BACKLOGF2).CometChatMessageComposer:user:/group:·parentMessageId(thread mode). A plain send needs nothing else.CometChatSearch[verified]:onConversationClicked/onMessageClicked(not the docs'onConversationItemClick/onMessageItemClick—DOCS-BACKLOGF3) ·onBack·user:/group:/searchInto scope it to one chat.
Any OTHER widget or a rarer prop → fetch its
.mdtwin viareferences/docs-map.md. Full catalog:cometchat-flutter-v6-components.
Golden path — the production-ready CORE surface (default for an unscoped "add chat"; grows on request)
Setup → init/login → gate the first frame on both resolving (show a loader; never render a CometChat* widget before login succeeds) → then:
- Conversations screen —
CometChatConversationsinsideScaffold+SafeArea. WireonItemTap→Navigator.pushthe message screen for that conversation'sUser/Group. Wire the global search the documented way:searchReadOnly: true+onSearchTap→ push aCometChatSearchscreen, whoseonConversationClicked/onMessageClickednavigate to the hit and whoseonBackpops. (Or sethideSearch: true— but never leave the field dead.) - Message screen —
CometChatMessageHeader+Expanded(child: CometChatMessageList(...))+CometChatMessageComposer, all carrying the SAMEuser:/group:.Expandedis what makes the list fill the screen; the header/composer keep their intrinsic height. LeaveScaffold.resizeToAvoidBottomInsetat its defaulttrueso the composer rides above the keyboard. The header'sshowBackButtondefaults totrue— wireonBacktoNavigator.pop. - Thread screen (DEFAULT — include unless the user opts out) — wire the list's
onThreadRepliesClickto push a screen withCometChatThreadedHeader(parentMessage:, loggedInUser:)— both required, and it has noonBack, so the screen's ownAppBarprovides back — plus aCometChatMessageList+CometChatMessageComposerthat each takeparentMessageId: parentMessage.idAND the sameuser:/group:as the parent chat. PassingparentMessageIdwithout the user/group target makes thread replies silently never send. - In-chat scoped search — Flutter's
CometChatMessageHeaderhas no search prop (unlike React). Put the action in the header'sauxiliaryButtonView/trailingViewslot — custom UI goes IN the slot, never stacked on top — and pushCometChatSearch(user: …/group: …)so it searches only that chat.
// [verified vs 6.1.0] the message screen — the shape the whole surface hangs off.
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
import 'package:flutter/material.dart';
class MessageScreen extends StatelessWidget {
final User? user;
final Group? group;
const MessageScreen({super.key, this.user, this.group});
@override
Widget build(BuildContext context) {
return Scaffold( // resizeToAvoidBottomInset defaults to true = keyboard-safe
body: SafeArea(
child: Column(
children: [
CometChatMessageHeader(user: user, group: group, onBack: () => Navigator.pop(context)),
Expanded( // REQUIRED — the list fills the remaining height
child: CometChatMessageList(
user: user,
group: group,
onThreadRepliesClick: (BaseMessage message, BuildContext context,
{CometChatMessageTemplate? template}) {
Navigator.push(context, MaterialPageRoute(
builder: (_) => ThreadScreen(parentMessage: message, user: user, group: group),
));
},
),
),
CometChatMessageComposer(user: user, group: group),
],
),
),
);
}
}
// The thread screen the callback pushes — part of the DEFAULT surface, not an extra.
// NOTE: the list AND composer each take parentMessageId *and* the same user:/group:
// as the parent chat. parentMessageId alone => replies silently never send.
class ThreadScreen extends StatelessWidget {
final BaseMessage parentMessage;
final User? user;
final Group? group;
const ThreadScreen({super.key, required this.parentMessage, this.user, this.group});
@override
Widget build(BuildContext context) {
return Scaffold(
// The thread screen's back affordance is the AppBar — CometChatThreadedHeader
// has NO onBack/onError param (the docs show one; it does not exist, DOCS-BACKLOG F5).
// A pushed route gets the back button automatically.
appBar: AppBar(title: const Text('Thread')),
body: SafeArea(
child: Column(
children: [
CometChatThreadedHeader( // note the 'ed' — see the map above
parentMessage: parentMessage, // NOT `message:` (DOCS-BACKLOG F1)
loggedInUser: CometChatUIKit.loggedInUser!, // required
),
Expanded(
child: CometChatMessageList(
user: user, group: group, parentMessageId: parentMessage.id,
),
),
CometChatMessageComposer(
user: user, group: group, parentMessageId: parentMessage.id,
),
],
),
),
);
}
}
SIZE it the mobile way —
references/layout.md. The kit's list widgets expand to fill their parent, so the failure mode here is an unbounded height error or a collapsed list, and the fix is always the same: give the list a bounded box (Expanded/Flexibleinside aColumn, or a sized parent) instead of letting content drive it. Never nest the surface in an unboundedSingleChildScrollView/ColumnwithoutExpanded. Match the data scope to the REQUEST. Real apps ship seeded groups, so a plainCometChatConversationslists both 1:1s and groups. A DM-only ask scopes the list to user conversations viaconversationsRequestBuilder; a groups-only app scopes to groups; a generic "add chat" keeps BOTH. Reuse the builder — never hand-roll a client-side filter, and don't add a Groups tab to a 1:1-only app. Prod auth: mint a per-user auth token server-side and callloginWithAuthToken— the Auth Key is dev-only (references/lifecycle.md).
Growing on request
Add each only when asked: Users / Groups / Calls tabs (CometChatUsers · CometChatGroups · CometChatCallLogs) · group details (CometChatGroupMembers + CometChatChangeScope) · calls (→ -calls; incoming calls = only navigatorKey: CallNavigationContext.navigatorKey on the root MaterialApp — never mount CometChatIncomingCall yourself, that doubles the kit's overlay) · features (→ -features). The full tab-based app is the union of these — recipe in -placement. A scoped-DOWN ask (chat tab, bottom sheet, embedded panel) → the matching -placement variant.
Deep references (load ONLY when the task needs them)
setup-credentials.md— detect signals · version_conflict · dashboard creds · the settings asset.lifecycle.md— init-once + hot restart · gating the first frame · prod auth-token · logout.layout.md— mobile sizing (bounded height ·Expanded· SafeArea · keyboard).docs-map.md— intent → live doc page (component twins + the SDK-docs section) · DOCS-GAP protocol · the pages that are wrong.anti-patterns.md— v5 carry-overs · unbounded height · render-before-login · the two-barrel trap.troubleshooting.md— symptom → cause → fix.
Common pitfalls (top 5 — full list in references/anti-patterns.md)
- version_conflict (v5 installed) · wrong Region · Auth Key shipped to prod · rendering a widget before
loginsucceeds. - Emitting v5 architecture into a v6 app. v6 REMOVED the extension pattern — no
UIKitSettings.extensions, noCometChatUIKitChatExtensions, noDataSource/ChatConfigurator/*ExtensionDecorator, noCometChatUIKit.getDataSource(). Dashboard-enabled extensions surface automatically with zero client code. Also gone: the v5 combined shells (CometChatConversationsWithMessages,CometChatUsersWithMessages,CometChatMessages,CometChatUI) — v6 has no shell widget; the host composes screens. Full map:cometchat-flutter-v6-migration. - Trusting the docs on the
[verified]signatures above. The thread-header params,onThreadRepliesClick, and the search callbacks were wrong on the live pages (DOCS-BACKLOG.mdPART 4 F1/F2/F3/F5) — all four are now corrected upstream (re-verified againstcometchat/docs@2ebb1db, 2026-09-09), so the[verified]names now agree with the pages; keep them.initFromSettingsis different: it is deliberately undocumented and stays that way (F4 WONTFIX), so this skill is its only reference.
Verify it works
Run the app: init then login both hit onSuccess → the conversations screen renders full-size (no sliver, no unbounded-height exception) → tap a conversation → messages send/receive → "reply in thread" opens the thread screen and back returns → the search field pushes search, a result navigates, back pops → the composer stays visible with the keyboard open → every pushed screen pops back. Blank screen ⇒ rendered before login resolved, or wrong Region/App ID. No bounded height, no thread wiring, or a dead search field ⇒ under-delivery. Tab-based app ⇒ verify per -placement.
Build the feature; do not write tests or run a test framework unless asked (
RULES.md) — the above is an advisory human pass.
Explain what you built (REQUIRED close — RULES.md §19)
Don't end on a silent code dump. Briefly: (1) what I wired (3–5 bullets, NAME the files); (2) decisions & why, flagging dev-only AS dev-only (Auth Key → server token for prod; the <uid>); (3) what I did NOT touch (additive — routing/state/theme intact). Then offer THREE options as a selectable choice and WAIT for the pick:
- ① Add another feature — first check what's already wired, and ASK which dashboard extensions are already on (you can't read per-app state). Suggest 3–4 that are neither (calls · push · polls · stickers · translation · AI smart replies · moderation). Never suggest reactions, mentions, quoted reply or threads — they are ON by default in v6; offer to customize them instead. →
-features/-calls. - ② Customize theming — ask for a brand/preset theme or talk through options →
-customization. - ③ Test it manually — do NOTHING further; hand it back.
A capability not in this pack: say so honestly + link CometChat's docs.
Signals
- GitHub stars
- 105
- Forks
- 2
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
cometchat-flutter-v6-core- Source
- github.com/cometchat/cometchat-skills