@cometchat/skills 3.0.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.
@@ -0,0 +1,335 @@
1
+ ---
2
+ name: cometchat-theming
3
+ description: Customize CometChat UI to match the user's app design system. Covers the CSS variable cascade, preset themes, brand color overrides, design system extraction, dark mode, and framework-specific override locations.
4
+ license: "MIT"
5
+ compatibility: "Node.js >=18; @cometchat/chat-uikit-react ^6; integration must already be applied"
6
+ allowed-tools: "executeBash, readFile, fileSearch, listDirectory, grepSearch"
7
+ metadata:
8
+ author: "CometChat"
9
+ version: "3.1.0"
10
+ tags: "cometchat theming css customization branding dark-mode"
11
+ ---
12
+
13
+ > **Companion skills:** `cometchat-core` covers CSS import placement
14
+ > and the one-import rule; `cometchat-customization` covers
15
+ > component-level CSS selectors for deeper overrides;
16
+ > `cometchat-troubleshooting` handles cases where the theme doesn't
17
+ > apply.
18
+
19
+ ## Purpose
20
+
21
+ Teach Claude how to theme CometChat in a v3 (AI-written) integration.
22
+ Themes are just CSS variable overrides — you write them directly into
23
+ the project's CSS (or, for Astro, the React island file). **Do not use
24
+ the `cometchat apply-theme` CLI command — it was a v2 tool that expects
25
+ a CLI-generated `.cometchat/state.json` marker that v3 integrations
26
+ don't create, and it will fail with "No integration found".**
27
+
28
+ ---
29
+
30
+ ## 1. How CometChat theming works
31
+
32
+ ### The CSS variable cascade
33
+
34
+ CometChat's entire visual identity is driven by **200+ CSS custom
35
+ properties** defined in `@cometchat/chat-uikit-react/css-variables.css`.
36
+ This file is imported once at the app root (see `cometchat-core`).
37
+ Every `<CometChat*>` component reads these variables — there is no
38
+ component-level style-props API for colors, fonts, or spacing.
39
+
40
+ To override: write CSS rules that set `--cometchat-*` variables on
41
+ `:root` (or a scoped container), **after** the `css-variables.css`
42
+ import. The cascade does the rest — every component picks up the new
43
+ values automatically.
44
+
45
+ ```css
46
+ /* Must appear AFTER the @import of css-variables.css */
47
+ :root {
48
+ --cometchat-primary-color: #6C63FF;
49
+ --cometchat-background-color-01: #FFFFFF;
50
+ --cometchat-text-color-primary: #141414;
51
+ --cometchat-font-family: "Inter", sans-serif;
52
+ --cometchat-radius-2: 8px;
53
+ }
54
+ ```
55
+
56
+ ### Dark mode
57
+
58
+ Two broad strategies — pick based on how the project already handles dark mode.
59
+
60
+ **Strategy A — OS-driven only** (simplest). Overrides live inside a `@media (prefers-color-scheme: dark)` block. The browser swaps themes based on the user's OS preference:
61
+
62
+ ```css
63
+ @media (prefers-color-scheme: dark) {
64
+ :root {
65
+ --cometchat-primary-color: #7B73FF;
66
+ --cometchat-background-color-01: #1A1A2E;
67
+ --cometchat-text-color-primary: #E0E0E0;
68
+ /* ... remaining dark overrides ... */
69
+ }
70
+ }
71
+ ```
72
+
73
+ **Strategy B — App-controlled theme toggle.** If the project already has a theme toggle (next-themes, Tailwind `dark:` prefix, React Context, etc.), wire CometChat's dark mode to the same trigger. The shared trigger is typically a CSS class or `data-theme` attribute on `<html>` or `<body>`. Scope the override to that selector:
74
+
75
+ ```css
76
+ /* next-themes default: applies a `.dark` class to <html> */
77
+ .dark :root {
78
+ --cometchat-primary-color: #7B73FF;
79
+ --cometchat-background-color-01: #1A1A2E;
80
+ --cometchat-text-color-primary: #E0E0E0;
81
+ }
82
+
83
+ /* OR if the project uses data-theme="dark" on <html> (common with Tailwind CSS v4) */
84
+ [data-theme="dark"] :root {
85
+ --cometchat-primary-color: #7B73FF;
86
+ --cometchat-background-color-01: #1A1A2E;
87
+ --cometchat-text-color-primary: #E0E0E0;
88
+ }
89
+
90
+ /* OR for Tailwind's `class` strategy with `darkMode: 'class'` in tailwind.config */
91
+ html.dark {
92
+ --cometchat-primary-color: #7B73FF;
93
+ --cometchat-background-color-01: #1A1A2E;
94
+ --cometchat-text-color-primary: #E0E0E0;
95
+ }
96
+ ```
97
+
98
+ **How to tell which selector the project uses:**
99
+
100
+ | Library / setup | Selector to target |
101
+ |---|---|
102
+ | `next-themes` (Next.js default) | `.dark` on `<html>` |
103
+ | Tailwind with `darkMode: 'class'` | `html.dark` (or `.dark` on any ancestor) |
104
+ | Tailwind with `darkMode: 'media'` | Matches `@media (prefers-color-scheme: dark)` — use Strategy A |
105
+ | Tailwind CSS v4 (`@custom-variant dark`) | `[data-theme="dark"]` by default |
106
+ | Radix UI / shadcn defaults | `.dark` class on `<html>` |
107
+ | Custom React Context (`useTheme()` hook) | Check what the context writes to the DOM — usually a class on `<html>` or `<body>` |
108
+
109
+ **Rule:** whichever selector is toggled by the app's theme system, use that same selector as the CometChat override's parent. The UI Kit components sit inside the app's DOM, so they inherit whatever variable values are active at the nearest matching scope.
110
+
111
+ **Do not** emit both Strategy A and Strategy B in the same stylesheet unless the user explicitly wants "follow OS except when app toggle is set." That's a legitimate pattern but usually over-engineered for a first integration — ship Strategy B alone if the project has a toggle, Strategy A if it doesn't.
112
+
113
+ ### Why Astro is different
114
+
115
+ Astro's `client:only="react"` islands run in isolation — global
116
+ stylesheets in `.astro` layouts do not cascade into them. CSS variable
117
+ overrides in a global `.css` file will have no effect on CometChat
118
+ components. The overrides must live **inside the React island `.tsx`
119
+ file** (typically `src/cometchat/ChatApp.tsx`), as an inline `<style>`
120
+ tag or a CSS import within the component.
121
+
122
+ ---
123
+
124
+ ## 2. Use this skill when
125
+
126
+ The user wants to customize the look and feel of an already-integrated
127
+ CometChat UI. Trigger phrases:
128
+
129
+ - `/cometchat theming`, `/cometchat theme`
130
+ - "match my brand colors"
131
+ - "make cometchat dark mode"
132
+ - "change the chat colors"
133
+ - "customize the cometchat ui"
134
+ - "the chat doesn't match my design system"
135
+
136
+ ## 3. Preconditions
137
+
138
+ The project must already have a CometChat integration. Check by looking
139
+ for `.cometchat/config.json` and the UI Kit dependency:
140
+
141
+ ```bash
142
+ test -f .cometchat/config.json && cat package.json | grep "@cometchat/chat-uikit-react"
143
+ ```
144
+
145
+ If neither is present, **stop** and tell the user to run `/cometchat`
146
+ to create an integration first. Theming requires the provider +
147
+ `css-variables.css` import to already be in place.
148
+
149
+ ## 4. When to use which path
150
+
151
+ | Situation | Path |
152
+ |---|---|
153
+ | Complete, opinionated theme fast | **Path A** — Preset |
154
+ | Brand color hex (and optionally font/radius) | **Path B** — Brand color |
155
+ | Existing Tailwind config or CSS custom properties | **Path C** — Design system extraction |
156
+
157
+ ---
158
+
159
+ ## 5. Preset values
160
+
161
+ Five built-in presets. All values are in the table below — write them
162
+ directly into the override CSS; do **not** try to call a CLI for this.
163
+
164
+ | Preset | `--cometchat-primary-color` | `--cometchat-text-color-primary` | `--cometchat-background-color-01` | `--cometchat-font-family` | `--cometchat-radius-2` | Dark mode included |
165
+ |---|---|---|---|---|---|---|
166
+ | `slack` | `#611f69` | `#1d1c1d` | `#ffffff` | `Lato, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif` | `8px` | no |
167
+ | `whatsapp` | `#25d366` | `#111b21` | `#f0f2f5` | `'Segoe UI', Helvetica, Arial, sans-serif` | `12px` | no |
168
+ | `imessage` | `#007aff` | `#000000` | `#ffffff` | `-apple-system, BlinkMacSystemFont, 'SF Pro Text', sans-serif` | `18px` | no |
169
+ | `discord` | `#5865f2` | `#dcddde` | `#36393f` | `'gg sans', 'Noto Sans', Helvetica, Arial, sans-serif` | `8px` | **yes** |
170
+ | `notion` | `#2eaadc` | `#37352f` | `#ffffff` | `-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif` | `6px` | no |
171
+
172
+ ## 6. Where to write the overrides
173
+
174
+ Target file is determined by `framework` in `.cometchat/config.json`:
175
+
176
+ | Framework | Target file |
177
+ |---|---|
178
+ | `reactjs` | `src/index.css` (append `:root { ... }` block after the existing import) |
179
+ | `nextjs` | `src/app/globals.css` (App Router) or `styles/globals.css` (Pages Router) |
180
+ | `react-router` | `app/app.css` (or `src/index.css` if you used a Vite-style structure) |
181
+ | `astro` | Inline `<style>` tag or imported CSS **inside** `src/cometchat/ChatApp.tsx` (see section 1 for why) |
182
+
183
+ The override block must be written **after** the existing
184
+ `@cometchat/chat-uikit-react/css-variables.css` import so it takes
185
+ precedence. If the project imports the CometChat CSS in a TSX file
186
+ (e.g. `src/main.tsx`), the override can still live in the adjacent
187
+ `index.css` because it appears in the DOM after the JS import resolves.
188
+
189
+ ## 7. Steps
190
+
191
+ ### Step 1 — Ask what theme source to use
192
+
193
+ If the user already specified a preset name, brand color, or pointed
194
+ to a design system file, skip to Step 2.
195
+
196
+ Otherwise use `AskUserQuestion`:
197
+ - **question:** "How do you want to theme CometChat?"
198
+ - **header:** "Theme"
199
+ - **multiSelect:** false
200
+ - **options:**
201
+ 1. label: "Use a preset", description: "Pick one of: slack, whatsapp, imessage, discord, notion."
202
+ 2. label: "Match my brand", description: "Give me your primary brand color (hex). I'll also ask about font and radius."
203
+ 3. label: "Match my existing design system", description: "Point me at your tailwind.config.{js,ts} or your CSS variables file. I'll extract the tokens."
204
+
205
+ ### Step 2 — Build the override block
206
+
207
+ **Path A — Preset:** Look up the preset in section 5's table. Emit a
208
+ `:root { ... }` block with those five variables. If the preset's
209
+ `Dark mode included` column is "yes" (currently just `discord`),
210
+ also emit a `@media (prefers-color-scheme: dark) { :root { ... } }`
211
+ block with sensible dark variants (invert background to dark, text to
212
+ light, keep primary).
213
+
214
+ **Path B — Custom brand color:** The user gave you a hex (e.g.
215
+ `#853953`). Emit at minimum:
216
+
217
+ ```css
218
+ :root {
219
+ --cometchat-primary-color: #853953;
220
+ }
221
+ ```
222
+
223
+ Then ask if they want:
224
+ - a matching font family (defaults to the project's existing font
225
+ stack from `body { font-family: ... }` in the project's main CSS)
226
+ - a border radius (defaults to `8px`)
227
+ - dark mode variants
228
+
229
+ ### Step 3 — Read the current CSS file
230
+
231
+ Read the target file (see section 6) so you can append to it instead
232
+ of overwriting existing rules. Check the file doesn't already have a
233
+ `--cometchat-primary-color` line — if it does, you're updating an
234
+ earlier theming pass; replace that block rather than duplicating.
235
+
236
+ ### Step 4 — Write / update the override block
237
+
238
+ Use `Edit` to insert or replace the `:root` block. Keep it grouped and
239
+ commented so the user can see where their theme lives:
240
+
241
+ ```css
242
+ /* CometChat theme override — edit these to change the chat UI */
243
+ :root {
244
+ --cometchat-primary-color: #853953;
245
+ --cometchat-font-family: "Inter", sans-serif;
246
+ }
247
+ ```
248
+
249
+ **Path C — Design system extraction:** Read
250
+ `tailwind.config.{js,ts}` (look for `theme.colors.primary`,
251
+ `theme.colors.background`, `theme.fontFamily.sans`,
252
+ `theme.borderRadius`) or the project's root CSS file (look for
253
+ `--primary`, `--background`, etc.). Extract the tokens. Then use
254
+ Path B's block shape with the extracted values.
255
+
256
+ ### Step 5 — Save the choice to config
257
+
258
+ ```bash
259
+ npx @cometchat/skills-cli config set theme "<preset-or-custom>"
260
+ ```
261
+
262
+ Where `<preset-or-custom>` is the preset name (e.g. `slack`) or
263
+ `custom` for Path B / Path C.
264
+
265
+ ### Step 6 — Tell the user to restart the dev server
266
+
267
+ The theme is applied. Tell the user:
268
+ 1. Restart the dev server (CSS changes need a fresh reload)
269
+ 2. Refresh the chat page
270
+ 3. Verify the colors match their design
271
+
272
+ If the theme doesn't appear to apply:
273
+ - Double-check the override block is **after** the css-variables.css
274
+ import in the DOM order
275
+ - For Astro: confirm the override is inside the `.tsx` island, not a
276
+ global `.css` file
277
+ - Route to `cometchat-troubleshooting` for deeper triage.
278
+
279
+ ## 8. Extended variable list (reference)
280
+
281
+ Beyond the five "headline" variables in the preset table, common ones
282
+ worth knowing:
283
+
284
+ | Variable | What it controls |
285
+ |---|---|
286
+ | `--cometchat-primary-color` | Active message bubble, primary buttons, brand accents |
287
+ | `--cometchat-text-color-primary` | Main body text |
288
+ | `--cometchat-text-color-secondary` | Timestamps, muted labels |
289
+ | `--cometchat-background-color-01` | Main app background |
290
+ | `--cometchat-background-color-02` | Panels (conversation list, details sidebar) |
291
+ | `--cometchat-background-color-03` | Hover / selected states |
292
+ | `--cometchat-border-color-light` | Dividers between rows |
293
+ | `--cometchat-font-family` | All text |
294
+ | `--cometchat-radius-2` | Medium radius (bubbles, buttons) |
295
+ | `--cometchat-radius-3` | Larger radius (panels) |
296
+
297
+ For the full 200+ list, query the docs MCP (see below) or read
298
+ `node_modules/@cometchat/chat-uikit-react/dist/styles/css-variables/css-variables.css`.
299
+
300
+ ## 9. Docs MCP contract
301
+
302
+ The CometChat docs MCP at `cometchat-docs` is the canonical source for:
303
+
304
+ - The full CSS variable list (200+ tokens) with descriptions
305
+ - Component-level styling selectors (`.cometchat-message-bubble-outgoing`,
306
+ `.cometchat-conversations-header`, etc.)
307
+ - Dark mode patterns beyond the simple invert
308
+ - Font / radius / spacing token names
309
+
310
+ **When to use it:**
311
+ - Component-level overrides beyond the 10 tokens above (e.g., "make
312
+ incoming bubbles green" needs a specific selector) — query the docs
313
+ MCP. Never invent CSS class names from memory.
314
+ - If the docs MCP is not installed and the user asks for this, tell
315
+ them: "I need the CometChat docs MCP for component-level styling.
316
+ Install it with `claude mcp add --transport http cometchat-docs
317
+ https://www.cometchat.com/docs/mcp` and re-run."
318
+
319
+ **Canonical reference URL:**
320
+ https://www.cometchat.com/docs/ui-kit/react/theme
321
+
322
+ ## Hard rules
323
+
324
+ - **Do NOT call `cometchat apply-theme`.** It's a v2 CLI command that
325
+ requires a CLI-generated `.cometchat/state.json` and fails on v3
326
+ AI-written integrations. Write CSS directly instead.
327
+ - Never apply theming to a project without an existing CometChat
328
+ integration (no `.cometchat/config.json` = no integration).
329
+ - Always write theme overrides **after** the css-variables.css import.
330
+ - Never invent CSS variable names. Use the preset table (section 5),
331
+ the common-variables table (section 8), or query the docs MCP.
332
+ - Never edit `node_modules` or vendor files.
333
+ - Astro is special: theme overrides must live inside the `.tsx`
334
+ React island file, not a global `.css`.
335
+ - Always use `npx @cometchat/skills-cli` for config saves.
@@ -0,0 +1,274 @@
1
+ ---
2
+ name: cometchat-troubleshooting
3
+ description: Diagnose and fix problems with a CometChat integration. Runs verify checks, detects drift, queries the docs MCP for symptom-to-cause lookups, and proposes targeted fixes. Works on any state — broken, missing, or drifted integrations.
4
+ license: "MIT"
5
+ compatibility: "Node.js >=18; @cometchat/chat-uikit-react ^6"
6
+ allowed-tools: "executeBash, readFile, fileSearch, listDirectory, grepSearch"
7
+ metadata:
8
+ author: "CometChat"
9
+ version: "3.0.0"
10
+ tags: "cometchat troubleshooting fix diagnose verify drift errors doctor"
11
+ ---
12
+
13
+ > **Companion skills:** `cometchat-core` is the authoritative source for
14
+ > correct init, login, and provider patterns; `cometchat-customization`
15
+ > explains why drift after customization is expected;
16
+ > `cometchat-theming` covers the CSS variable cascade for
17
+ > theme-not-applying symptoms.
18
+
19
+ ## Purpose
20
+
21
+ This skill teaches Claude how to diagnose CometChat integration problems
22
+ systematically. It explains what each diagnostic tool checks, what the
23
+ known failure modes are and why they happen, and how to distinguish
24
+ infrastructure problems (env vars, dashboard config, network) from code
25
+ problems (wrong init sequence, missing CSS import, drift).
26
+
27
+ ---
28
+
29
+ ## 1. Use this skill when
30
+
31
+ The user has a problem with their CometChat integration. Trigger phrases:
32
+
33
+ - `/cometchat troubleshoot`
34
+ - `/cometchat fix`
35
+ - `/cometchat fix <symptom>`
36
+ - "chat isn't loading"
37
+ - "i'm getting a cometchat error"
38
+ - "the chat is broken"
39
+ - "blank screen on /chat"
40
+ - "401 Unauthorized from cometchat"
41
+ - "css-variables not loading"
42
+ - "the chat doesn't show messages"
43
+
44
+ ## 2. Docs MCP contract
45
+
46
+ The CometChat docs MCP at `cometchat-docs` is a **hard requirement** for
47
+ this skill. `cometchat doctor` handles the local diagnostic checks
48
+ (integration state, drift, env vars, AST verify rules), but for any
49
+ symptom that doesn't match a doctor known-issue code, the MCP is the
50
+ canonical source for symptom → cause → fix.
51
+
52
+ **Hard rules:**
53
+
54
+ 1. **Always run `cometchat doctor` first** — its known-issues table
55
+ covers the common failure modes (env-placeholder, env-missing, drift,
56
+ init-before-login, no-auth-key-in-source).
57
+ 2. **For symptoms NOT in doctor's table**, query the docs MCP with the
58
+ exact error message or symptom keywords. Never guess at the cause.
59
+ 3. **If the docs MCP is not installed**, STOP. Tell the user: "Doctor
60
+ didn't recognize this symptom and I need the CometChat docs MCP to
61
+ diagnose further. Install it with `claude mcp add --transport http
62
+ cometchat-docs https://www.cometchat.com/docs/mcp` and re-run."
63
+ 4. **Never blame the user's code** if doctor + MCP both pass — the issue
64
+ is probably infrastructure (network, dashboard config, auth provider).
65
+ 5. **Canonical reference URL:**
66
+ https://www.cometchat.com/docs/ui-kit/react/troubleshooting
67
+
68
+ ---
69
+
70
+ ## 3. What `cometchat doctor` actually checks
71
+
72
+ Understanding what doctor checks helps you interpret its output and
73
+ know when to look beyond it:
74
+
75
+ 1. **Detection** — reads `.cometchat/state.json` to confirm an
76
+ integration exists. If absent, reports `integrated: false`.
77
+
78
+ 2. **Env var checks** — reads the framework's env file (`.env` for
79
+ Vite/Astro/React Router, `.env.local` for Next.js). Checks each
80
+ `COMETCHAT_*` variable for:
81
+ - Presence (key exists in the file)
82
+ - Placeholder sentinels (`YOUR_*_HERE` still present = warning)
83
+
84
+ 3. **AST verify** — parses owned TypeScript files and runs 5 checks:
85
+ - `css_variables_imported_once` — counts
86
+ `@cometchat/chat-uikit-react/css-variables.css` imports (must be
87
+ exactly 1)
88
+ - `init_before_login` — confirms `login()` call sites appear after
89
+ `init()` resolves (in a `.then()` chain or after `await`)
90
+ - `render_gated_on_login_resolve` — checks that `createRoot().render()`
91
+ or JSX is not called at module top level before init completes
92
+ - `no_auth_key_in_source` — searches string literals for patterns
93
+ matching auth key format (should be in `.env`, not source)
94
+ - `error_ui_visible_on_failure` — confirms that catch handlers set
95
+ state variables that render visible error UI
96
+
97
+ 4. **Drift detection** — checksums each file in `state.files_owned`
98
+ against the originally applied template. Reports modified or missing
99
+ files.
100
+
101
+ **When to go beyond doctor:** doctor passes but the app still shows a
102
+ blank screen → likely SSR, network, or dashboard config. Doctor only
103
+ checks local code and env files.
104
+
105
+ ---
106
+
107
+ ## 4. Steps
108
+
109
+ ### Step 1 — Triage: read the project state
110
+
111
+ ```bash
112
+ npx @cometchat/skills-cli info --json
113
+ ```
114
+
115
+ Three possible outcomes:
116
+
117
+ | `info` says | Diagnosis | Next step |
118
+ |---|---|---|
119
+ | `integrated: false` | No integration exists | Check for **partial state** (below). If none, tell user to run `/cometchat` first and stop. |
120
+ | `integrated: true, drift.has_drift: true` | User edited owned files | Step 2 + flag the drift |
121
+ | `integrated: true, drift.has_drift: false` | Clean integration but something is broken | Step 2 |
122
+
123
+ If drift is detected, surface the modified file list verbatim. **Do not
124
+ automatically offer to restore** — drift after using
125
+ `cometchat-customization` is expected and correct. Ask the user whether
126
+ the changes were intentional before suggesting any restore.
127
+
128
+ ### Step 1a — Partial-state recovery (aborted /cometchat runs)
129
+
130
+ `info` returning `integrated: false` doesn't always mean the project is
131
+ clean. `/cometchat` may have been started, errored out, or been
132
+ interrupted mid-flow, leaving the project in an inconsistent half-state.
133
+ Check these markers in parallel before offering to re-run from scratch:
134
+
135
+ ```bash
136
+ # All four of these can exist independently after a partial run
137
+ test -f .cometchat/config.json && cat .cometchat/config.json
138
+ grep -l "COMETCHAT_APP_ID" .env .env.local 2>/dev/null
139
+ find src app -name "CometChatProvider.*" -o -name "ChatDrawer.*" 2>/dev/null
140
+ grep -rln "@cometchat/chat-uikit-react" src app 2>/dev/null | head -5
141
+ ```
142
+
143
+ Interpret the combination:
144
+
145
+ | Markers present | Likely state | Recovery |
146
+ |---|---|---|
147
+ | config.json exists, no `COMETCHAT_APP_ID` in env | Onboarding was started but app provisioning didn't finish | Re-run the provision step only: `npx @cometchat/skills-cli provision setup --app-id <id> --framework <k>` (or `--name <n>` for a new app) |
148
+ | env has credentials, no config.json | Credentials were pasted manually but integration wasn't recorded | Run `npx @cometchat/skills-cli config init --json` to regenerate config.json from detect + env |
149
+ | Provider/drawer files written, no CSS import, no provider mount | Integration code was partially written | Ask user whether to finish the integration (route through `/cometchat` resuming from the plan step) or delete the partial files and start clean |
150
+ | CSS import present, no provider wired | CSS-only leftover from an earlier attempt | Delete the stray `css-variables.css` import or mount the provider — ask user |
151
+ | All four present but `info` still says `integrated: false` | `.cometchat/state.json` was never written — the `/cometchat` flow skipped Step 8 (`state record`), so every Phase B command (`info`, `status`, `doctor`, `verify`, `uninstall`, `apply-theme`, etc.) thinks the project is un-integrated | Run `state record` to rebuild the state.json from what's on disk. Read the list of CometChat files the user has, then: `npx @cometchat/skills-cli state record --framework "<fw>" --placement "<type>" --placement-path "<path>" --auth-mode "<mode>" --files-owned "<new-files>" --files-patched "<patched-files-with-patch-id>" --json`. After this, `info` / `status` / `doctor` all work correctly. |
152
+
153
+ **Rule:** always show the user which markers you found before proposing a
154
+ recovery path. Never delete config.json, env entries, or source files
155
+ without explicit approval.
156
+
157
+ ### Step 2 — Run verify
158
+
159
+ ```bash
160
+ npx @cometchat/skills-cli verify --json
161
+ ```
162
+
163
+ This runs the AST checks. The output looks like:
164
+
165
+ ```json
166
+ {
167
+ "status": "fail",
168
+ "checks": {
169
+ "css_variables_imported_once": { "status": "fail", "reason": "..." },
170
+ "init_before_login": { "status": "pass" },
171
+ ...
172
+ }
173
+ }
174
+ ```
175
+
176
+ For each failed check, look up the fix in the table below or via the docs MCP.
177
+
178
+ ### Step 3 — Match symptom to known issues
179
+
180
+ Common doctor issue codes + verify failures and their fixes:
181
+
182
+ | Issue code / failed check | Likely cause | Fix |
183
+ |---|---|---|
184
+ | `env-placeholder` | CometChat env vars still contain `YOUR_*_HERE` sentinels — user ran integration but never filled in real credentials | Open the env file doctor names (`.env` or `.env.local`) and replace each `YOUR_*_HERE` with the real value from https://app.cometchat.com → Your App → API & Auth Keys. This is the most common post-init failure. |
185
+ | `env-missing` | A required CometChat env var key isn't in the env file at all | Run `cometchat apply --force-overwrite` to re-emit the placeholders, then fill them in. |
186
+ | `drift-modified` | Owned files have been edited since apply | If the user used `cometchat-customization` or hand-edited intentionally, this is **expected** — not a bug. `cometchat info` flags it because the checksum changed. Only offer `cometchat apply --force` if the drift is accidental. **Ask before restoring** — force-apply destroys intentional customizations. |
187
+ | `drift-missing` | An owned file was deleted | Run `cometchat apply --force` to recreate the missing file. |
188
+ | `css_variables_imported_once` (count=0) | The css-variables.css import was removed | Re-add `@import url("@cometchat/chat-uikit-react/css-variables.css");` to the top of `src/index.css` (or the per-framework target). For Astro, it goes inside the .tsx file, not the global CSS. |
189
+ | `css_variables_imported_once` (count>1) | Imported in multiple places | Remove the duplicate. Keep only the one in the canonical location. |
190
+ | `init_before_login` | Code calls `CometChatUIKit.login` before `CometChatUIKit.init` resolves | In the provider pattern (Next.js, Astro, React Router SSR): use `await init(settings)` followed by `await login()` sequentially inside `useEffect`. In the entry-file pattern (Vite/CRA): chain `init(settings).then(() => login()).then(() => mount())`. See `cometchat-core` section 6. |
191
+ | `render_gated_on_login_resolve` | `createRoot(...).render` is called at top level, not inside a `mount()` function | Wrap render in `mount()` and call it only after `login()` resolves. For React island frameworks, gate render with `if (!user) return null`. |
192
+ | `no_auth_key_in_source` | Auth Key hardcoded in a source file | Move it to `.env` and reference via the framework's env prefix (`import.meta.env.VITE_COMETCHAT_AUTH_KEY`, `process.env.NEXT_PUBLIC_COMETCHAT_AUTH_KEY`, etc.). |
193
+ | `error_ui_visible_on_failure` | No visible error state rendered on init/login failure | In the component that calls `init()`/`login()`, add a catch handler that sets an error state, then render: `<div style={{ color: "red", padding: 16 }}>CometChat Error: {error}</div>`. The full pattern is in `cometchat-core` section 6 (CometChatProvider). |
194
+
195
+ For symptoms not in this table, proceed to Step 4.
196
+
197
+ ### Step 4 — Framework-specific patterns
198
+
199
+ Many issues are framework-specific. Check against these common patterns:
200
+
201
+ | Framework | Symptom | Likely cause | Fix |
202
+ |---|---|---|---|
203
+ | Next.js | Blank screen / hydration mismatch | CometChat components rendered on the server | Add `"use client"` to the file, or use `dynamic(() => import(...), { ssr: false })`. See `cometchat-core` section 5. |
204
+ | Astro | Theme not applying | CSS override in a global `.css` file instead of inside the React island | Move `--cometchat-*` overrides inside `src/cometchat/ChatApp.tsx`. See `cometchat-theming` section 1. |
205
+ | Astro | Components not rendering | Missing `client:only="react"` directive | Add `client:only="react"` to the island component in the `.astro` file. |
206
+ | React Router v7 | `window is not defined` at build | CometChat imported in a module that runs on the server | Wrap in `React.lazy` + `Suspense` with a `ClientOnly` guard. See `cometchat-react-router-patterns` section 3. |
207
+ | Vite / CRA | CSS variables not taking effect | Override block appears BEFORE the `@import` of css-variables.css | Reorder: the `@import` must come first, overrides must follow. |
208
+ | Any | 401 Unauthorized | Wrong or expired auth key in `.env` | Check `.env` for `YOUR_AUTH_KEY_HERE`. Replace with real value from app.cometchat.com → API & Auth Keys. |
209
+ | Any | `CometChat is not initialized` | Component renders before `init()` resolves | Use the provider pattern from `cometchat-core` section 6, or add an `isReady` gate before rendering CometChat components. |
210
+ | Any (React 19) | `Cannot update a component (ForwardRef) while rendering a different component` | Known React 19 warning from CometChat UI Kit internals (`closePopover` calls setState during render). **Not a bug in your code.** | Ignore — this is a cosmetic warning from inside the UI Kit's minified bundle. The UI works correctly. Will be fixed in a future UI Kit release. Do NOT try to patch this in user code. |
211
+
212
+ ### Step 5 — Symptom-driven lookup via the docs MCP
213
+
214
+ If the user has reported a specific symptom that isn't covered by verify
215
+ checks or the framework table, query the CometChat docs MCP:
216
+
217
+ ```
218
+ Use the cometchat-docs MCP to search for "<symptom keywords>"
219
+ ```
220
+
221
+ Common symptom searches:
222
+
223
+ | Symptom | MCP search query |
224
+ |---|---|
225
+ | Blank screen at /chat | "blank screen ssr nextjs" or "blank screen react-router" |
226
+ | 401 Unauthorized | "401 unauthorized authentication" |
227
+ | Chat doesn't load | "chat not loading init login" |
228
+ | Build error | "<exact error message from build output>" |
229
+ | CORS error | "cors origin allowed" |
230
+ | Mixed user/group error | "user group same component" |
231
+ | Theme not applying | "theming css variables override" |
232
+
233
+ The docs MCP returns the canonical fix. Apply it as a targeted patch.
234
+
235
+ ### Step 6 — Propose the fix
236
+
237
+ Show the user:
238
+ 1. What's broken (verify output, drift report, or symptom)
239
+ 2. The likely cause (from the table or docs MCP)
240
+ 3. The exact fix (file path + content change)
241
+ 4. Whether to:
242
+ - **Patch the specific issue** — targeted edit to the broken file.
243
+ Preferred for most issues.
244
+ - **Restore from the registry** — `cometchat apply --force` rewrites
245
+ all owned files back to their template state. Safe only if the
246
+ user hasn't customized them. **Ask first.**
247
+ - **Re-run the integration cleanly** — `cometchat uninstall --force`
248
+ followed by `/cometchat`. Wipes state.json and starts over. Last
249
+ resort.
250
+
251
+ For dashboard/network/auth issues, the fix is on the user's side
252
+ (CometChat dashboard, .env values, network connectivity) — `cometchat
253
+ doctor` surfaces the issue and the fix verbatim. Don't try to "fix"
254
+ infrastructure issues from the CLI.
255
+
256
+ ### Step 7 — Verify the fix
257
+
258
+ After any fix is applied, re-run:
259
+
260
+ ```bash
261
+ npx @cometchat/skills-cli verify --json
262
+ ```
263
+
264
+ Confirm `status: "pass"`. If anything is still failing, repeat from Step 2.
265
+
266
+ ## Hard rules
267
+
268
+ - Never apply a fix without showing the user what will change first.
269
+ - Never invent error causes — query the docs MCP if you don't know.
270
+ - Never blame the user's code if the verify checks are passing — the issue
271
+ is probably in the docs MCP territory (network, auth, dashboard config).
272
+ - For drift, default to **showing** the drift and asking if it was
273
+ intentional, not auto-restoring. Drift after customization is expected.
274
+ - Always use `npx @cometchat/skills-cli`.