{"id":"1d8cf6f6-3b45-4d9c-890d-fc8f6a996220","shortId":"GyN5JE","kind":"skill","title":"cometchat-angular-production","tagline":"Production-readiness for Angular — server-minted auth tokens, user management CRUD, external-backend recipes (Express / Hono / Firebase Functions / Vercel). Angular has no API routes, so the backend is always external.","description":"## Purpose\n\nTeaches Claude how to move an Angular CometChat integration from dev-mode Auth Key to production-ready server-minted auth tokens + user CRUD. Covers:\n\n1. Why the dev `authKey` can't ship to production\n2. Auth Key vs REST API Key — which lives where\n3. Server endpoint recipes (Express / Hono / Firebase Functions / Vercel)\n4. Client-side: `CometChatUIKit.login({ authToken })` + token refresh\n5. User CRUD endpoints + auth-provider integration (Firebase Auth / Supabase / Clerk / Auth0)\n6. Security checklist\n\n**Read `cometchat-angular-core` first** — production just swaps one call on the init service, but understanding the init lifecycle is the prerequisite.\n\nGround truth: `docs/ui-kit/angular/methods`, and the cross-platform REST API at `https://{APP_ID}.api-{REGION}.cometchat.io/v3/`.\n\n---\n\n## 1. Why production auth matters\n\nIn dev mode, `CometChatUIKit.login({ uid: \"...\" })` uses the `authKey` passed to `UIKitSettingsBuilder`. That key is bundled into your Angular JavaScript. Anyone can open DevTools → Sources → search for the key string and use it to log in as **ANY** user in your CometChat app — read private messages, send as other users, access every conversation.\n\nProduction MUST use server-side token generation:\n\n- Your **server** holds the REST API Key (a different key from the client Auth Key).\n- On user login, your server calls CometChat's REST API with the REST API Key to mint a short-lived **Auth Token** for that specific UID.\n- Your Angular client receives the Auth Token and calls `CometChatUIKit.login({ authToken })`.\n- If the token leaks, the blast radius is one user session, not your whole app.\n\n---\n\n## 2. Auth Key vs REST API Key — two different keys\n\n| Key | Where in dashboard | Purpose | Where it lives |\n|---|---|---|---|\n| **Auth Key** | \"Auth Keys\" table | Client-side SDK `login({ uid })` in dev mode | **Client bundle** — dev only. Never in production builds. |\n| **REST API Key** | \"REST API Keys\" table | Server-to-server: token generation, user CRUD | **Server only.** Never in `environment.ts`, `environment.prod.ts`, or any Angular file. |\n\nIf the project only has an Auth Key, the user needs to generate a REST API Key in the dashboard: **API & Auth Keys → REST API Keys → Add Key**. Pick \"Full Access\" for server-side use.\n\n---\n\n## 3. The token auth pattern (4 steps)\n\n```\n1. User logs into YOUR auth (Firebase Auth / Supabase / Clerk / Auth0 / custom)\n   ↓\n2. Angular app asks YOUR backend for a CometChat auth token\n   ↓ (POST /api/cometchat-token with Authorization: Bearer <jwt>)\n3. Backend calls CometChat REST API → gets an Auth Token for that UID\n   ↓ POST https://{APP_ID}.api-{REGION}.cometchat.io/v3/users/{uid}/auth_tokens\n     with header apiKey: <REST_API_KEY>\n   ↓\n4. Angular calls CometChatUIKit.login({ authToken: \"...\" })\n```\n\nThe Angular client never sees the REST API Key. The server never ships a password or email to the client.\n\n---\n\n## 4. Server endpoint recipes\n\nAngular projects don't have built-in API routes. You need a separate backend.\n\n### 4a. Express (Node.js backend)\n\n```typescript\n// server/routes/cometchat-token.ts\nimport { Router } from \"express\";\nimport { requireAuth } from \"../middleware/auth\";\n\nconst router = Router();\nconst APP_ID = process.env.COMETCHAT_APP_ID!;\nconst REGION = process.env.COMETCHAT_REGION!;\nconst REST_API_KEY = process.env.COMETCHAT_REST_API_KEY!;\n\nrouter.post(\"/cometchat-token\", requireAuth, async (req, res) => {\n  const uid = req.user.id;  // from authenticated session — NOT from request body\n\n  const r = await fetch(\n    `https://${APP_ID}.api-${REGION}.cometchat.io/v3/users/${encodeURIComponent(uid)}/auth_tokens`,\n    {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        appId: APP_ID,\n        apiKey: REST_API_KEY,\n      },\n      body: JSON.stringify({}),\n    }\n  );\n\n  if (!r.ok) {\n    return res.status(r.status).json({ error: \"Failed to generate auth token\" });\n  }\n\n  const data = await r.json();\n  return res.json({ authToken: data.data.authToken });\n});\n\nexport default router;\n```\n\n### 4b. Hono (Cloudflare Workers / Bun / Node)\n\n```typescript\nimport { Hono } from \"hono\";\n\nconst app = new Hono();\n\napp.post(\"/api/cometchat-token\", async (c) => {\n  const user = c.get(\"user\");\n  if (!user) return c.json({ error: \"unauthorized\" }, 401);\n\n  const r = await fetch(\n    `https://${c.env.COMETCHAT_APP_ID}.api-${c.env.COMETCHAT_REGION}.cometchat.io/v3/users/${encodeURIComponent(user.id)}/auth_tokens`,\n    {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        appId: c.env.COMETCHAT_APP_ID,\n        apiKey: c.env.COMETCHAT_REST_API_KEY,\n      },\n      body: JSON.stringify({}),\n    }\n  );\n\n  if (!r.ok) return c.json({ error: \"token mint failed\" }, 502);\n  const data = await r.json();\n  return c.json({ authToken: data.data.authToken });\n});\n```\n\n### 4c. Firebase Cloud Functions\n\n```typescript\nimport { onCall, HttpsError } from \"firebase-functions/v2/https\";\n\nexport const getCometChatToken = onCall(\n  { secrets: [\"COMETCHAT_APP_ID\", \"COMETCHAT_REGION\", \"COMETCHAT_REST_API_KEY\"] },\n  async (request) => {\n    if (!request.auth) throw new HttpsError(\"unauthenticated\", \"Sign in required\");\n    const uid = request.auth.uid;\n\n    const r = await fetch(\n      `https://${process.env.COMETCHAT_APP_ID}.api-${process.env.COMETCHAT_REGION}.cometchat.io/v3/users/${encodeURIComponent(uid)}/auth_tokens`,\n      {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n          appId: process.env.COMETCHAT_APP_ID!,\n          apiKey: process.env.COMETCHAT_REST_API_KEY!,\n        },\n        body: JSON.stringify({}),\n      }\n    );\n\n    if (!r.ok) throw new HttpsError(\"internal\", \"token mint failed\");\n    const data = await r.json();\n    return { authToken: data.data.authToken };\n  }\n);\n```\n\n### 4d. Vercel Serverless / Next.js API Route\n\n```typescript\n// pages/api/cometchat-token.ts\nimport type { NextApiRequest, NextApiResponse } from \"next\";\nimport { getServerSession } from \"next-auth\";\n\nexport default async function handler(req: NextApiRequest, res: NextApiResponse) {\n  if (req.method !== \"POST\") return res.status(405).end();\n\n  const session = await getServerSession(req, res, authOptions);\n  if (!session?.user) return res.status(401).json({ error: \"unauthorized\" });\n\n  const uid = session.user.id;\n  const r = await fetch(\n    `https://${process.env.COMETCHAT_APP_ID}.api-${process.env.COMETCHAT_REGION}.cometchat.io/v3/users/${encodeURIComponent(uid)}/auth_tokens`,\n    {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        appId: process.env.COMETCHAT_APP_ID!,\n        apiKey: process.env.COMETCHAT_REST_API_KEY!,\n      },\n      body: JSON.stringify({}),\n    }\n  );\n\n  if (!r.ok) return res.status(502).json({ error: \"token mint failed\" });\n  const data = await r.json();\n  return res.json({ authToken: data.data.authToken });\n}\n```\n\n---\n\n## 5. Client-side: Angular service for production auth\n\n```typescript\n// cometchat-auth.service.ts\nimport { Injectable } from \"@angular/core\";\nimport { HttpClient, HttpHeaders } from \"@angular/common/http\";\nimport { CometChatUIKit } from \"@cometchat/chat-uikit-angular\";\nimport { environment } from \"../environments/environment\";\nimport { firstValueFrom } from \"rxjs\";\n\n@Injectable({ providedIn: \"root\" })\nexport class CometChatAuthService {\n  constructor(private http: HttpClient) {}\n\n  async loginWithToken(appJwt: string): Promise<void> {\n    // 1. Check if already logged in\n    const existing = await CometChatUIKit.getLoggedinUser();\n    if (existing) return;\n\n    // 2. Fetch CometChat auth token from your backend\n    const response = await firstValueFrom(\n      this.http.post<{ authToken: string }>(\n        environment.cometchat.tokenEndpoint,\n        {},\n        { headers: new HttpHeaders({ Authorization: `Bearer ${appJwt}` }) }\n      )\n    );\n\n    // 3. Login with the auth token\n    await CometChatUIKit.login({ authToken: response.authToken });\n  }\n\n  async logout(): Promise<void> {\n    await CometChatUIKit.logout();\n  }\n}\n```\n\n```typescript\n// app.component.ts — production-aware init\nimport { Component, OnInit } from \"@angular/core\";\nimport { CometChatAuthService } from \"./cometchat-auth.service\";\nimport { YourAuthService } from \"./your-auth.service\";  // your existing auth\n\n@Component({ selector: \"app-root\", templateUrl: \"./app.component.html\" })\nexport class AppComponent implements OnInit {\n  isReady = false;\n\n  constructor(\n    private cometChatAuth: CometChatAuthService,\n    private yourAuth: YourAuthService\n  ) {}\n\n  ngOnInit(): void {\n    // CometChat.init() already called via APP_INITIALIZER\n    this.yourAuth.getJwt().then((jwt) => {\n      return this.cometChatAuth.loginWithToken(jwt);\n    }).then(() => {\n      this.isReady = true;\n    }).catch(console.error);\n  }\n}\n```\n\n### Production environment file\n\n```typescript\n// src/environments/environment.prod.ts\nexport const environment = {\n  production: true,\n  cometchat: {\n    appId: \"YOUR_APP_ID\",\n    region: \"us\",\n    // No authKey in production\n    tokenEndpoint: \"https://api.yourapp.com/cometchat-token\",\n  },\n};\n```\n\n---\n\n## 6. User management CRUD\n\nWhen someone signs up in your app, create a matching CometChat user on your backend.\n\n### 6a. Create a user on signup\n\n```typescript\nasync function createCometChatUser(uid: string, name: string, avatarUrl?: string) {\n  const r = await fetch(\n    `https://${APP_ID}.api-${REGION}.cometchat.io/v3/users`,\n    {\n      method: \"POST\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        appId: APP_ID,\n        apiKey: REST_API_KEY,\n      },\n      body: JSON.stringify({ uid, name, avatar: avatarUrl }),\n    }\n  );\n  if (!r.ok) throw new Error(`CometChat user create failed: ${await r.text()}`);\n  return r.json();\n}\n```\n\n### 6b. Update a user on profile change\n\n```typescript\nasync function updateCometChatUser(uid: string, updates: { name?: string; avatar?: string }) {\n  const r = await fetch(\n    `https://${APP_ID}.api-${REGION}.cometchat.io/v3/users/${encodeURIComponent(uid)}`,\n    {\n      method: \"PUT\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        appId: APP_ID,\n        apiKey: REST_API_KEY,\n      },\n      body: JSON.stringify(updates),\n    }\n  );\n  if (!r.ok) throw new Error(`CometChat user update failed: ${await r.text()}`);\n  return r.json();\n}\n```\n\n### 6c. Delete a user on account deletion\n\n```typescript\nasync function deleteCometChatUser(uid: string) {\n  const r = await fetch(\n    `https://${APP_ID}.api-${REGION}.cometchat.io/v3/users/${encodeURIComponent(uid)}`,\n    {\n      method: \"DELETE\",\n      headers: {\n        \"Content-Type\": \"application/json\",\n        appId: APP_ID,\n        apiKey: REST_API_KEY,\n      },\n      body: JSON.stringify({ permanent: true }),\n    }\n  );\n  if (!r.ok) throw new Error(`CometChat user delete failed: ${await r.text()}`);\n}\n```\n\n---\n\n## 7. Environment variables — split between client + server\n\n| Variable | Location | Visibility |\n|---|---|---|\n| `COMETCHAT_APP_ID` | `environment.ts` + server | OK client-side |\n| `COMETCHAT_REGION` | `environment.ts` + server | OK client-side |\n| `COMETCHAT_AUTH_KEY` | **Dev `environment.ts` only.** Remove from `environment.prod.ts`. | Should NEVER ship in a production Angular build |\n| `COMETCHAT_REST_API_KEY` | **Server only.** Your backend's env. | Never in any Angular file, ever |\n| `COMETCHAT_TOKEN_ENDPOINT` | `environment.prod.ts` | Your backend URL — safe in client bundle |\n\n---\n\n## 8. Security checklist\n\nBefore releasing to production:\n\n- [ ] `authKey` removed from `environment.prod.ts`\n- [ ] Production init uses `UIKitSettingsBuilder` without `.setAuthKey()`\n- [ ] Production login uses `CometChatUIKit.login({ authToken })`, not `login({ uid })`\n- [ ] `COMETCHAT_REST_API_KEY` lives only on your backend (check with `grep -r REST_API_KEY src/`)\n- [ ] Token endpoint is behind auth — unauthenticated users can't mint a token for an arbitrary UID\n- [ ] UID derivation on the token endpoint comes from the authenticated session, NOT from the request body\n- [ ] Rate limit on the token endpoint (prevents abuse)\n- [ ] HTTPS-only — no HTTP in production\n- [ ] User CRUD endpoints are authenticated (or called from webhooks with signature verification)\n- [ ] CometChat user deletion happens on account deletion (GDPR / privacy compliance)\n\n---\n\n## 9. Anti-patterns\n\n1. **NEVER put the REST API Key in any Angular file.** Not in `environment.ts`, `environment.prod.ts`, `assets/`, or any TypeScript file. Angular bundles everything in `src/` into the client JavaScript.\n\n2. **NEVER let the client specify the UID to mint a token for.** The server must derive UID from the authenticated session. A `POST /cometchat-token { uid: \"...\" }` that trusts the body is equivalent to no auth.\n\n3. **Don't cache the auth token to localStorage forever.** It expires. Either re-mint on every cold start or store with a short TTL and refresh on 401.\n\n4. **Don't use `login({ uid })` in production.** `uid` mode requires an Auth Key on the UIKitSettings. In production, set neither `authKey` on the builder nor call `login({ uid })`.\n\n5. **Don't forget user CRUD.** A user who signs up in your app but has no matching CometChat user will get \"user does not exist\" errors on `login({ authToken })`.\n\n---\n\n## Skill routing reference\n\n| Skill | When to route |\n|---|---|\n| `cometchat-angular-core` | Init / login / module setup — prerequisite |\n| `cometchat-angular-components` | The base component props |\n| `cometchat-angular-placement` | Where your chat UI goes |\n| `cometchat-angular-patterns` | Angular-specific auth guard + APP_INITIALIZER |\n| `cometchat-angular-theming` | Theme customization |\n| `cometchat-angular-features` | Feature flags |\n| `cometchat-angular-customization` | If customization depends on server-side data |\n| `cometchat-angular-production` | This skill — server tokens + user CRUD |\n| `cometchat-angular-troubleshooting` | 401 on token fetch, \"user does not exist\" on login |","tags":["cometchat","angular","production","skills","agent-skills","ai-agent","chat","claude-code","cursor","messaging","nextjs","react"],"capabilities":["skill","source-cometchat","skill-cometchat-angular-production","topic-agent-skills","topic-ai-agent","topic-chat","topic-claude-code","topic-cometchat","topic-cursor","topic-messaging","topic-nextjs","topic-react","topic-react-native","topic-ui-kit"],"categories":["cometchat-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cometchat/cometchat-skills/cometchat-angular-production","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cometchat/cometchat-skills","source_repo":"https://github.com/cometchat/cometchat-skills","install_from":"skills.sh"}},"qualityScore":"0.463","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 27 github stars · SKILL.md body (14,029 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:04:48.467Z","embedding":null,"createdAt":"2026-05-07T13:05:07.807Z","updatedAt":"2026-05-18T19:04:48.467Z","lastSeenAt":"2026-05-18T19:04:48.467Z","tsv":"'/api/cometchat-token':425,619 '/app.component.html':1007 '/auth_tokens':451,563,648,740,845 '/cometchat-auth.service':993 '/cometchat-token':535,1065,1500 '/environments/environment':909 '/middleware/auth':512 '/v2/https':696 '/v3/':159 '/v3/users':1111 '/v3/users/':449 '/v3/users/$':560,645,737,842,1173,1229 '/your-auth.service':997 '1':66,160,401,929,1447 '2':76,293,413,942,1476 '3':86,394,429,964,1511 '4':95,399,455,480,1541 '401':632,823,1540,1682 '405':809 '4a':499 '4b':603 '4c':684 '4d':775 '5':103,882,1570 '502':675,868 '6':116,1066 '6a':1085 '6b':1145 '6c':1206 '7':1261 '8':1332 '9':1443 'abus':1413 'access':214,388 'account':1211,1438 'add':384 'alreadi':932,1025 'alway':36 'angular':3,9,27,45,122,182,268,356,414,456,461,484,886,1303,1318,1456,1467,1609,1618,1626,1635,1638,1646,1652,1658,1670,1680 'angular-specif':1637 'angular/common/http':901 'angular/core':896,989 'anti':1445 'anti-pattern':1444 'anyon':184 'api':30,81,151,155,230,249,253,298,334,337,373,378,382,434,445,467,492,528,532,556,576,640,663,709,732,755,779,837,860,1107,1124,1169,1188,1225,1244,1307,1359,1371,1452 'api.yourapp.com':1064 'api.yourapp.com/cometchat-token':1063 'apikey':454,574,660,752,857,1122,1186,1242 'app':153,206,292,415,443,517,520,554,572,615,638,658,703,730,750,835,855,1004,1028,1054,1076,1105,1120,1167,1184,1223,1240,1272,1583,1642 'app-root':1003 'app.component.ts':980 'app.post':618 'appcompon':1010 'appid':571,656,748,853,1052,1119,1183,1239 'appjwt':926,963 'application/json':570,655,747,852,1118,1182,1238 'arbitrari':1388 'ask':416 'asset':1462 'async':537,620,711,797,924,974,1092,1153,1214 'auth':13,52,61,77,108,112,163,238,261,272,294,311,313,364,379,397,406,408,422,437,590,794,890,945,968,1000,1289,1378,1510,1516,1553,1640 'auth-provid':107 'auth0':115,411 'authent':544,1399,1425,1496 'authkey':70,172,1059,1339,1562 'authopt':817 'author':427,961 'authtoken':100,277,459,598,682,773,880,955,972,1353,1599 'avatar':1130,1161 'avatarurl':1099,1131 'await':552,594,635,678,727,770,813,832,876,937,952,970,977,1103,1141,1165,1202,1221,1259 'awar':983 'backend':20,34,418,430,498,502,949,1084,1312,1326,1365 'base':1621 'bearer':428,962 'behind':1377 'blast':283 'bodi':549,578,665,757,862,1126,1190,1246,1405,1505 'build':332,1304 'builder':1565 'built':490 'built-in':489 'bun':607 'bundl':179,326,1331,1468 'c':621 'c.env.cometchat':637,641,657,661 'c.get':624 'c.json':629,670,681 'cach':1514 'call':129,245,275,431,457,1026,1427,1567 'catch':1039 'chang':1151 'chat':1630 'check':930,1366 'checklist':118,1334 'class':918,1009 'claud':40 'clerk':114,410 'client':97,237,269,317,325,462,479,884,1266,1278,1286,1330,1474,1480 'client-sid':96,316,883,1277,1285 'cloud':686 'cloudflar':605 'cold':1529 'come':1396 'cometchat':2,46,121,205,246,421,432,702,705,707,944,1051,1080,1137,1198,1255,1271,1280,1288,1305,1321,1357,1433,1588,1608,1617,1625,1634,1645,1651,1657,1669,1679 'cometchat-angular-compon':1616 'cometchat-angular-cor':120,1607 'cometchat-angular-custom':1656 'cometchat-angular-featur':1650 'cometchat-angular-pattern':1633 'cometchat-angular-plac':1624 'cometchat-angular-product':1,1668 'cometchat-angular-them':1644 'cometchat-angular-troubleshoot':1678 'cometchat-auth.service.ts':892 'cometchat.init':1024 'cometchat.io':158,448,559,644,736,841,1110,1172,1228 'cometchat.io/v3/':157 'cometchat.io/v3/users':1109 'cometchat.io/v3/users/':447 'cometchat.io/v3/users/$':558,643,735,840,1171,1227 'cometchat/chat-uikit-angular':905 'cometchatauth':1017 'cometchatauthservic':919,991,1018 'cometchatuikit':903 'cometchatuikit.getloggedinuser':938 'cometchatuikit.login':99,168,276,458,971,1352 'cometchatuikit.logout':978 'complianc':1442 'compon':986,1001,1619,1622 'console.error':1040 'const':513,516,522,526,540,550,592,614,622,633,676,698,722,725,768,811,827,830,874,935,950,1047,1101,1163,1219 'constructor':920,1015 'content':568,653,745,850,1116,1180,1236 'content-typ':567,652,744,849,1115,1179,1235 'convers':216 'core':123,1610 'cover':65 'creat':1077,1086,1139 'createcometchatus':1094 'cross':148 'cross-platform':147 'crud':17,64,105,347,1069,1422,1575,1677 'custom':412,1649,1659,1661 'dashboard':306,377 'data':593,677,769,875,1667 'data.data.authtoken':599,683,774,881 'default':601,796 'delet':1207,1212,1233,1257,1435,1439 'deletecometchatus':1216 'depend':1662 'deriv':1391,1492 'dev':50,69,166,323,327,1291 'dev-mod':49 'devtool':187 'differ':233,301 'docs/ui-kit/angular/methods':144 'either':1523 'email':476 'encodeuricompon':561,646,738,843,1174,1230 'end':810 'endpoint':88,106,482,1323,1375,1395,1411,1423 'env':1314 'environ':907,1042,1048,1262 'environment.cometchat.tokenendpoint':957 'environment.prod.ts':353,1296,1324,1342,1461 'environment.ts':352,1274,1282,1292,1460 'equival':1507 'error':586,630,671,825,870,1136,1197,1254,1596 'ever':1320 'everi':215,1528 'everyth':1469 'exist':936,940,999,1595,1689 'expir':1522 'export':600,697,795,917,1008,1046 'express':22,90,500,508 'extern':19,37 'external-backend':18 'fail':587,674,767,873,1140,1201,1258 'fals':1014 'featur':1653,1654 'fetch':553,636,728,833,943,1104,1166,1222,1685 'file':357,1043,1319,1457,1466 'firebas':24,92,111,407,685,694 'firebase-funct':693 'first':124 'firstvaluefrom':911,953 'flag':1655 'forev':1520 'forget':1573 'full':387 'function':25,93,687,695,798,1093,1154,1215 'gdpr':1440 'generat':224,345,370,589 'get':435,1591 'getcometchattoken':699 'getserversess':790,814 'goe':1632 'grep':1368 'ground':142 'guard':1641 'handler':799 'happen':1436 'header':453,566,651,743,848,958,1114,1178,1234 'hold':227 'hono':23,91,604,611,613,617 'http':922,1418 'httpclient':898,923 'httpheader':899,960 'https':1415 'https-on':1414 'httpserror':691,717,763 'id':154,444,518,521,555,573,639,659,704,731,751,836,856,1055,1106,1121,1168,1185,1224,1241,1273 'implement':1011 'import':505,509,610,689,783,789,893,897,902,906,910,985,990,994 'init':132,137,984,1344,1611 'initi':1029,1643 'inject':894,914 'integr':47,110 'intern':764 'isreadi':1013 'javascript':183,1475 'json':585,824,869 'json.stringify':579,666,758,863,1127,1191,1247 'jwt':1032,1035 'key':53,78,82,177,192,231,234,239,254,295,299,302,303,312,314,335,338,365,374,380,383,385,468,529,533,577,664,710,756,861,1125,1189,1245,1290,1308,1360,1372,1453,1554 'leak':281 'let':1478 'lifecycl':138 'limit':1407 'live':84,260,310,1361 'localstorag':1519 'locat':1269 'log':198,403,933 'login':242,320,965,1350,1355,1545,1568,1598,1612,1691 'loginwithtoken':925 'logout':975 'manag':16,1068 'match':1079,1587 'matter':164 'messag':209 'method':564,649,741,846,1112,1176,1232 'mint':12,60,256,673,766,872,1383,1485,1526 'mode':51,167,324,1550 'modul':1613 'move':43 'must':218,1491 'name':1097,1129,1159 'need':368,495 'neither':1561 'never':329,350,463,471,1298,1315,1448,1477 'new':616,716,762,959,1135,1196,1253 'next':788,793 'next-auth':792 'next.js':778 'nextapirequest':785,801 'nextapirespons':786,803 'ngoninit':1022 'node':608 'node.js':501 'ok':1276,1284 'oncal':690,700 'one':128,286 'oninit':987,1012 'open':186 'pages/api/cometchat-token.ts':782 'pass':173 'password':474 'pattern':398,1446,1636 'perman':1248 'pick':386 'placement':1627 'platform':149 'post':424,442,565,650,742,806,847,1113,1499 'prerequisit':141,1615 'prevent':1412 'privaci':1441 'privat':208,921,1016,1019 'process.env.cometchat':519,524,530,729,733,749,753,834,838,854,858 'product':4,6,56,75,125,162,217,331,889,982,1041,1049,1061,1302,1338,1343,1349,1420,1548,1559,1671 'production-awar':981 'production-readi':5,55 'profil':1150 'project':360,485 'promis':928,976 'prop':1623 'provid':109 'providedin':915 'purpos':38,307 'put':1177,1449 'r':551,634,726,831,1102,1164,1220,1369 'r.json':595,679,771,877,1144,1205 'r.ok':581,668,760,865,1133,1194,1251 'r.status':584 'r.text':1142,1203,1260 'radius':284 'rate':1406 're':1525 're-mint':1524 'read':119,207 'readi':7,57 'receiv':270 'recip':21,89,483 'refer':1602 'refresh':102,1538 'region':156,446,523,525,557,642,706,734,839,1056,1108,1170,1226,1281 'releas':1336 'remov':1294,1340 'req':538,800,815 'req.method':805 'req.user.id':542 'request':548,712,1404 'request.auth':714 'request.auth.uid':724 'requir':721,1551 'requireauth':510,536 'res':539,802,816 'res.json':597,879 'res.status':583,808,822,867 'respons':951 'response.authtoken':973 'rest':80,150,229,248,252,297,333,336,372,381,433,466,527,531,575,662,708,754,859,1123,1187,1243,1306,1358,1370,1451 'return':582,596,628,669,680,772,807,821,866,878,941,1033,1143,1204 'root':916,1005 'rout':31,493,780,1601,1606 'router':506,514,515,602 'router.post':534 'rxjs':913 'safe':1328 'sdk':319 'search':189 'secret':701 'secur':117,1333 'see':464 'selector':1002 'send':210 'separ':497 'server':11,59,87,221,226,244,341,343,348,391,470,481,1267,1275,1283,1309,1490,1665,1674 'server-mint':10,58 'server-sid':220,390,1664 'server-to-serv':340 'server/routes/cometchat-token.ts':504 'serverless':777 'servic':133,887 'session':288,545,812,819,1400,1497 'session.user.id':829 'set':1560 'setauthkey':1348 'setup':1614 'ship':73,472,1299 'short':259,1535 'short-liv':258 'side':98,222,318,392,885,1279,1287,1666 'sign':719,1072,1579 'signatur':1431 'signup':1090 'skill':1600,1603,1673 'skill-cometchat-angular-production' 'someon':1071 'sourc':188 'source-cometchat' 'specif':265,1639 'specifi':1481 'split':1264 'src':1373,1471 'src/environments/environment.prod.ts':1045 'start':1530 'step':400 'store':1532 'string':193,927,956,1096,1098,1100,1157,1160,1162,1218 'supabas':113,409 'swap':127 'tabl':315,339 'teach':39 'templateurl':1006 'theme':1647,1648 'this.cometchatauth.loginwithtoken':1034 'this.http.post':954 'this.isready':1037 'this.yourauth.getjwt':1030 'throw':715,761,1134,1195,1252 'token':14,62,101,223,262,273,280,344,396,423,438,591,672,765,871,946,969,1322,1374,1385,1394,1410,1487,1517,1675,1684 'tokenendpoint':1062 'topic-agent-skills' 'topic-ai-agent' 'topic-chat' 'topic-claude-code' 'topic-cometchat' 'topic-cursor' 'topic-messaging' 'topic-nextjs' 'topic-react' 'topic-react-native' 'topic-ui-kit' 'troubleshoot':1681 'true':1038,1050,1249 'trust':1503 'truth':143 'ttl':1536 'two':300 'type':569,654,746,784,851,1117,1181,1237 'typescript':503,609,688,781,891,979,1044,1091,1152,1213,1465 'ui':1631 'uid':169,266,321,441,450,541,562,723,739,828,844,1095,1128,1156,1175,1217,1231,1356,1389,1390,1483,1493,1501,1546,1549,1569 'uikitset':1557 'uikitsettingsbuild':175,1346 'unauthent':718,1379 'unauthor':631,826 'understand':135 'updat':1146,1158,1192,1200 'updatecometchatus':1155 'url':1327 'us':1057 'use':170,195,219,393,1345,1351,1544 'user':15,63,104,202,213,241,287,346,367,402,623,625,627,820,1067,1081,1088,1138,1148,1199,1209,1256,1380,1421,1434,1574,1577,1589,1592,1676,1686 'user.id':647 'variabl':1263,1268 'vercel':26,94,776 'verif':1432 'via':1027 'visibl':1270 'void':1023 'vs':79,296 'webhook':1429 'whole':291 'without':1347 'worker':606 'yourauth':1020 'yourauthservic':995,1021","prices":[{"id":"45000fa9-6a8e-4b34-992d-ba6c67feef09","listingId":"1d8cf6f6-3b45-4d9c-890d-fc8f6a996220","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cometchat","category":"cometchat-skills","install_from":"skills.sh"},"createdAt":"2026-05-07T13:05:07.807Z"}],"sources":[{"listingId":"1d8cf6f6-3b45-4d9c-890d-fc8f6a996220","source":"github","sourceId":"cometchat/cometchat-skills/cometchat-angular-production","sourceUrl":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-angular-production","isPrimary":false,"firstSeenAt":"2026-05-07T13:05:07.807Z","lastSeenAt":"2026-05-18T19:04:48.467Z"}],"details":{"listingId":"1d8cf6f6-3b45-4d9c-890d-fc8f6a996220","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cometchat","slug":"cometchat-angular-production","github":{"repo":"cometchat/cometchat-skills","stars":27,"topics":["agent-skills","ai-agent","chat","claude-code","cometchat","cursor","messaging","nextjs","react","react-native","ui-kit"],"license":null,"html_url":"https://github.com/cometchat/cometchat-skills","pushed_at":"2026-05-18T05:04:24Z","description":"Add CometChat chat to any React, Next.js, React Native, Angular, Android, iOS, or Flutter project through your AI coding agent. Works with Claude Code, Cursor, Codex, VS Code Copilot, Windsurf, Cline, Kiro, and 50+ more agents.","skill_md_sha":"68ebd354d39a4dde8164880bd42175ec994a5d6c","skill_md_path":"skills/cometchat-angular-production/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-angular-production"},"layout":"multi","source":"github","category":"cometchat-skills","frontmatter":{"name":"cometchat-angular-production","license":"MIT","description":"Production-readiness for Angular — server-minted auth tokens, user management CRUD, external-backend recipes (Express / Hono / Firebase Functions / Vercel). Angular has no API routes, so the backend is always external.","compatibility":"Angular >=12 <=15; @cometchat/chat-uikit-angular ^4; @cometchat/chat-sdk-javascript ^4"},"skills_sh_url":"https://skills.sh/cometchat/cometchat-skills/cometchat-angular-production"},"updatedAt":"2026-05-18T19:04:48.467Z"}}