{"id":"ffe1bbaa-97aa-4ae5-9cca-3449a45dbbbc","shortId":"gJC82v","kind":"skill","title":"cometchat-ios-production","tagline":"Production-ready CometChat iOS setup — server-side auth tokens, security best practices, and deployment checklist.","description":"## Purpose\n\nThis skill teaches how to prepare your CometChat iOS integration for production. It covers replacing development Auth Keys with server-side auth tokens, security best practices, and a deployment checklist.\n\n---\n\n## 1. Development vs Production Authentication\n\n### Development Mode (Auth Key)\n\nIn development, you use the Auth Key directly in your app:\n\n```swift\n// ⚠️ DEVELOPMENT ONLY — Never ship this to production\nCometChatUIKit.login(uid: \"user-123\") { result in\n    // ...\n}\n```\n\n**Problems with Auth Key in production:**\n- Auth Key is embedded in your app binary\n- Anyone can decompile your app and extract it\n- Attackers can impersonate any user\n- No server-side validation of user identity\n\n### Production Mode (Auth Token)\n\nIn production, your server generates short-lived auth tokens:\n\n```\n┌─────────────┐     1. Login      ┌─────────────┐\n│   iOS App   │ ───────────────► │ Your Server │\n└─────────────┘                   └─────────────┘\n       │                                │\n       │                                │ 2. Verify user\n       │                                │    Generate token\n       │                                ▼\n       │                         ┌─────────────┐\n       │                         │  CometChat  │\n       │                         │    API      │\n       │                         └─────────────┘\n       │                                │\n       │     3. Return auth token       │\n       │ ◄──────────────────────────────┘\n       │\n       │ 4. Login with token\n       ▼\n┌─────────────┐\n│  CometChat  │\n│     SDK     │\n└─────────────┘\n```\n\n---\n\n## 2. Server-Side Token Generation\n\n### Your Server Endpoint\n\nCreate an endpoint that:\n1. Authenticates the user (your existing auth system)\n2. Calls CometChat API to generate an auth token\n3. Returns the token to the iOS app\n\n**Example (Node.js/Express):**\n\n```javascript\nconst express = require('express');\nconst axios = require('axios');\n\nconst app = express();\n\nconst COMETCHAT_APP_ID = process.env.COMETCHAT_APP_ID;\nconst COMETCHAT_API_KEY = process.env.COMETCHAT_API_KEY;  // REST API Key\nconst COMETCHAT_REGION = process.env.COMETCHAT_REGION;\n\napp.post('/api/cometchat/token', async (req, res) => {\n    try {\n        // 1. Verify the user is authenticated (your auth system)\n        const userId = req.user.id;  // From your auth middleware\n        \n        if (!userId) {\n            return res.status(401).json({ error: 'Unauthorized' });\n        }\n        \n        // 2. Generate CometChat auth token\n        const response = await axios.post(\n            `https://${COMETCHAT_APP_ID}.api-${COMETCHAT_REGION}.cometchat.io/v3/users/${userId}/auth_tokens`,\n            {},\n            {\n                headers: {\n                    'apiKey': COMETCHAT_API_KEY,\n                    'Content-Type': 'application/json'\n                }\n            }\n        );\n        \n        // 3. Return the token\n        res.json({\n            authToken: response.data.data.authToken\n        });\n        \n    } catch (error) {\n        console.error('CometChat token error:', error.response?.data || error.message);\n        res.status(500).json({ error: 'Failed to generate token' });\n    }\n});\n```\n\n**Example (Python/Flask):**\n\n```python\nfrom flask import Flask, jsonify, request\nimport requests\nimport os\n\napp = Flask(__name__)\n\nCOMETCHAT_APP_ID = os.environ.get('COMETCHAT_APP_ID')\nCOMETCHAT_API_KEY = os.environ.get('COMETCHAT_API_KEY')\nCOMETCHAT_REGION = os.environ.get('COMETCHAT_REGION')\n\n@app.route('/api/cometchat/token', methods=['POST'])\ndef get_cometchat_token():\n    # 1. Verify user is authenticated (your auth system)\n    user_id = request.user.id  # From your auth middleware\n    \n    if not user_id:\n        return jsonify({'error': 'Unauthorized'}), 401\n    \n    # 2. Generate CometChat auth token\n    url = f'https://{COMETCHAT_APP_ID}.api-{COMETCHAT_REGION}.cometchat.io/v3/users/{user_id}/auth_tokens'\n    \n    headers = {\n        'apiKey': COMETCHAT_API_KEY,\n        'Content-Type': 'application/json'\n    }\n    \n    response = requests.post(url, headers=headers)\n    \n    if response.status_code == 200:\n        data = response.json()\n        return jsonify({'authToken': data['data']['authToken']})\n    else:\n        return jsonify({'error': 'Failed to generate token'}), 500\n```\n\n### CometChat REST API Reference\n\n**Create Auth Token:**\n```\nPOST https://{appId}.api-{region}.cometchat.io/v3/users/{uid}/auth_tokens\n\nHeaders:\n  apiKey: YOUR_REST_API_KEY\n  Content-Type: application/json\n\nResponse:\n{\n  \"data\": {\n    \"uid\": \"user-123\",\n    \"authToken\": \"user-123_abc123xyz...\"\n  }\n}\n```\n\n**Create User (if needed):**\n```\nPOST https://{appId}.api-{region}.cometchat.io/v3/users\n\nHeaders:\n  apiKey: YOUR_REST_API_KEY\n  Content-Type: application/json\n\nBody:\n{\n  \"uid\": \"user-123\",\n  \"name\": \"John Doe\",\n  \"avatar\": \"https://example.com/avatar.jpg\"\n}\n```\n\n---\n\n## 3. iOS Implementation\n\n### CometChatManager for Production\n\n```swift\nimport Foundation\nimport CometChatUIKitSwift\nimport CometChatSDK\n\nfinal class CometChatManager {\n    \n    static let shared = CometChatManager()\n    \n    private(set) var isInitialized = false\n    private(set) var currentUser: User?\n    \n    private init() {}\n    \n    // MARK: - Initialization (No Auth Key needed)\n    \n    func initialize(completion: @escaping (Result<Bool, Error>) -> Void) {\n        guard !isInitialized else {\n            completion(.success(true))\n            return\n        }\n        \n        // Note: No authKey in production!\n        let uiKitSettings = UIKitSettings()\n            .set(appID: AppConfig.cometChatAppID)\n            .set(region: AppConfig.cometChatRegion)\n            .subscribePresenceForAllUsers()\n            .build()\n        \n        CometChatUIKit(uiKitSettings: uiKitSettings) { [weak self] result in\n            DispatchQueue.main.async {\n                switch result {\n                case .success(let success):\n                    self?.isInitialized = success\n                    self?.currentUser = CometChatUIKit.getLoggedInUser()\n                    completion(.success(success))\n                case .failure(let error):\n                    completion(.failure(error))\n                }\n            }\n        }\n    }\n    \n    // MARK: - Production Login\n    \n    func login(completion: @escaping (Result<User, Error>) -> Void) {\n        guard isInitialized else {\n            completion(.failure(CometChatError.notInitialized))\n            return\n        }\n        \n        // Check for existing session\n        if let user = CometChatUIKit.getLoggedInUser() {\n            currentUser = user\n            completion(.success(user))\n            return\n        }\n        \n        // Fetch auth token from your server\n        fetchAuthToken { [weak self] result in\n            switch result {\n            case .success(let authToken):\n                self?.loginWithToken(authToken, completion: completion)\n            case .failure(let error):\n                completion(.failure(error))\n            }\n        }\n    }\n    \n    private func fetchAuthToken(completion: @escaping (Result<String, Error>) -> Void) {\n        guard let url = URL(string: \"\\(AppConfig.apiBaseURL)/api/cometchat/token\") else {\n            completion(.failure(CometChatError.invalidURL))\n            return\n        }\n        \n        var request = URLRequest(url: url)\n        request.httpMethod = \"POST\"\n        request.setValue(\"application/json\", forHTTPHeaderField: \"Content-Type\")\n        \n        // Add your auth header (e.g., JWT token)\n        if let authToken = AuthManager.shared.accessToken {\n            request.setValue(\"Bearer \\(authToken)\", forHTTPHeaderField: \"Authorization\")\n        }\n        \n        URLSession.shared.dataTask(with: request) { data, response, error in\n            if let error = error {\n                completion(.failure(error))\n                return\n            }\n            \n            guard let data = data else {\n                completion(.failure(CometChatError.noData))\n                return\n            }\n            \n            do {\n                let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]\n                if let authToken = json?[\"authToken\"] as? String {\n                    completion(.success(authToken))\n                } else {\n                    completion(.failure(CometChatError.invalidResponse))\n                }\n            } catch {\n                completion(.failure(error))\n            }\n        }.resume()\n    }\n    \n    private func loginWithToken(_ authToken: String, completion: @escaping (Result<User, Error>) -> Void) {\n        CometChatUIKit.login(authToken: authToken) { [weak self] result in\n            DispatchQueue.main.async {\n                switch result {\n                case .success(let user):\n                    self?.currentUser = user\n                    completion(.success(user))\n                case .onError(let error):\n                    completion(.failure(error))\n                }\n            }\n        }\n    }\n    \n    // MARK: - Logout\n    \n    func logout(completion: @escaping (Result<Void, Error>) -> Void) {\n        guard let user = currentUser else {\n            completion(.success(()))\n            return\n        }\n        \n        CometChatUIKit.logout(user: user) { [weak self] result in\n            DispatchQueue.main.async {\n                switch result {\n                case .success:\n                    self?.currentUser = nil\n                    completion(.success(()))\n                case .onError(let error):\n                    completion(.failure(error))\n                }\n            }\n        }\n    }\n}\n\n// MARK: - Errors\n\nenum CometChatError: LocalizedError {\n    case notInitialized\n    case invalidURL\n    case noData\n    case invalidResponse\n    \n    var errorDescription: String? {\n        switch self {\n        case .notInitialized:\n            return \"CometChat is not initialized\"\n        case .invalidURL:\n            return \"Invalid API URL\"\n        case .noData:\n            return \"No data received from server\"\n        case .invalidResponse:\n            return \"Invalid response from server\"\n        }\n    }\n}\n```\n\n### App Configuration\n\n```swift\n// AppConfig.swift\nimport Foundation\n\nstruct AppConfig {\n    \n    // CometChat\n    static let cometChatAppID: String = {\n        guard let appID = Bundle.main.object(forInfoDictionaryKey: \"CometChatAppID\") as? String else {\n            fatalError(\"CometChatAppID not found in Info.plist\")\n        }\n        return appID\n    }()\n    \n    static let cometChatRegion: String = {\n        guard let region = Bundle.main.object(forInfoDictionaryKey: \"CometChatRegion\") as? String else {\n            fatalError(\"CometChatRegion not found in Info.plist\")\n        }\n        return region\n    }()\n    \n    // Your API\n    static let apiBaseURL: String = {\n        #if DEBUG\n        return \"https://api-staging.yourapp.com\"\n        #else\n        return \"https://api.yourapp.com\"\n        #endif\n    }()\n}\n```\n\n### Info.plist Configuration\n\n```xml\n<key>CometChatAppID</key>\n<string>$(COMETCHAT_APP_ID)</string>\n<key>CometChatRegion</key>\n<string>$(COMETCHAT_REGION)</string>\n```\n\n### xcconfig Files\n\n**Debug.xcconfig:**\n```\nCOMETCHAT_APP_ID = your_app_id\nCOMETCHAT_REGION = us\n```\n\n**Release.xcconfig:**\n```\nCOMETCHAT_APP_ID = your_app_id\nCOMETCHAT_REGION = us\n```\n\n---\n\n## 4. User Provisioning\n\n### Create Users on Your Server\n\nWhen a user signs up in your app, create them in CometChat:\n\n```javascript\n// On your server - user registration endpoint\napp.post('/api/register', async (req, res) => {\n    const { email, password, name } = req.body;\n    \n    // 1. Create user in your database\n    const user = await createUserInDatabase({ email, password, name });\n    \n    // 2. Create user in CometChat\n    await axios.post(\n        `https://${COMETCHAT_APP_ID}.api-${COMETCHAT_REGION}.cometchat.io/v3/users`,\n        {\n            uid: user.id,\n            name: user.name,\n            avatar: user.avatarUrl\n        },\n        {\n            headers: {\n                'apiKey': COMETCHAT_API_KEY,\n                'Content-Type': 'application/json'\n            }\n        }\n    );\n    \n    res.json({ success: true, userId: user.id });\n});\n```\n\n### Update User Profile\n\nWhen user updates their profile:\n\n```javascript\napp.put('/api/profile', async (req, res) => {\n    const { name, avatar } = req.body;\n    const userId = req.user.id;\n    \n    // 1. Update in your database\n    await updateUserInDatabase(userId, { name, avatar });\n    \n    // 2. Update in CometChat\n    await axios.put(\n        `https://${COMETCHAT_APP_ID}.api-${COMETCHAT_REGION}.cometchat.io/v3/users/${userId}`,\n        { name, avatar },\n        {\n            headers: {\n                'apiKey': COMETCHAT_API_KEY,\n                'Content-Type': 'application/json'\n            }\n        }\n    );\n    \n    res.json({ success: true });\n});\n```\n\n---\n\n## 5. Security Best Practices\n\n### Never Expose API Keys\n\n❌ **Wrong:**\n```swift\n// Never do this!\nlet apiKey = \"abc123xyz\"  // Hardcoded in app\n```\n\n✅ **Correct:**\n```swift\n// API keys stay on your server\n// iOS app only receives short-lived auth tokens\n```\n\n### Validate User Identity\n\nAlways verify user identity on your server before generating tokens:\n\n```javascript\napp.post('/api/cometchat/token', authenticateMiddleware, async (req, res) => {\n    // authenticateMiddleware verifies the user's JWT/session\n    const userId = req.user.id;  // Verified user ID\n    \n    // Generate token only for verified users\n    // ...\n});\n```\n\n### Use HTTPS\n\nAlways use HTTPS for API communication:\n\n```swift\n// ✅ Correct\nlet url = URL(string: \"https://api.yourapp.com/api/cometchat/token\")\n\n// ❌ Wrong\nlet url = URL(string: \"http://api.yourapp.com/api/cometchat/token\")\n```\n\n### Token Expiration\n\nAuth tokens have a default expiration. Handle token refresh:\n\n```swift\nfunc handleTokenExpired() {\n    // Clear current session\n    CometChatManager.shared.logout { _ in\n        // Re-login to get new token\n        CometChatManager.shared.login { result in\n            switch result {\n            case .success:\n                print(\"Re-authenticated successfully\")\n            case .failure(let error):\n                print(\"Re-authentication failed: \\(error)\")\n                // Navigate to login screen\n            }\n        }\n    }\n}\n```\n\n### App Transport Security\n\nEnsure ATS is properly configured in `Info.plist`:\n\n```xml\n<key>NSAppTransportSecurity</key>\n<dict>\n    <key>NSAllowsArbitraryLoads</key>\n    <false/>\n</dict>\n```\n\n---\n\n## 6. Error Handling\n\n### Handle Authentication Errors\n\n```swift\nfunc handleCometChatError(_ error: Error) {\n    if let cometChatError = error as? CometChatException {\n        switch cometChatError.errorCode {\n        case \"ERR_UID_NOT_FOUND\":\n            // User doesn't exist in CometChat\n            // Create user on your server, then retry\n            createUserAndRetry()\n            \n        case \"AUTH_ERR_AUTH_TOKEN_NOT_FOUND\":\n            // Invalid or expired token\n            refreshTokenAndRetry()\n            \n        case \"ERR_NOT_LOGGED_IN\":\n            // User not logged in\n            navigateToLogin()\n            \n        default:\n            showError(cometChatError.errorDescription ?? \"Unknown error\")\n        }\n    }\n}\n```\n\n### Retry Logic\n\n```swift\nfunc loginWithRetry(maxAttempts: Int = 3, completion: @escaping (Result<User, Error>) -> Void) {\n    var attempts = 0\n    \n    func attempt() {\n        attempts += 1\n        \n        CometChatManager.shared.login { result in\n            switch result {\n            case .success(let user):\n                completion(.success(user))\n            case .failure(let error):\n                if attempts < maxAttempts {\n                    // Wait and retry\n                    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {\n                        attempt()\n                    }\n                } else {\n                    completion(.failure(error))\n                }\n            }\n        }\n    }\n    \n    attempt()\n}\n```\n\n---\n\n## 7. Deployment Checklist\n\n### Before Submitting to App Store\n\n- [ ] **Remove Auth Key from code** — Use server-side tokens only\n- [ ] **Configure production API URL** — Point to production server\n- [ ] **Test with production CometChat app** — Create separate prod app in dashboard\n- [ ] **Enable required extensions** — Polls, stickers, AI features in dashboard\n- [ ] **Configure push notifications** — Upload APNs certificate to dashboard\n- [ ] **Test on real devices** — Calls and push don't work on simulator\n- [ ] **Review Info.plist permissions** — Camera, microphone, notifications\n- [ ] **Test logout flow** — Ensure clean session termination\n- [ ] **Test offline behavior** — App should handle network issues gracefully\n- [ ] **Review error messages** — User-friendly error handling\n\n### CometChat Dashboard Configuration\n\n- [ ] **Create production app** — Separate from development\n- [ ] **Configure webhooks** — If using server-side events\n- [ ] **Set up push notifications** — APNs certificate uploaded\n- [ ] **Enable required extensions** — Only what you need\n- [ ] **Configure AI features** — If using AI capabilities\n- [ ] **Review rate limits** — Understand your plan limits\n- [ ] **Set up monitoring** — Enable analytics and logging\n\n### Server Configuration\n\n- [ ] **Secure API keys** — Store in environment variables\n- [ ] **Implement rate limiting** — Prevent abuse\n- [ ] **Add request validation** — Validate all inputs\n- [ ] **Set up logging** — Monitor token generation\n- [ ] **Configure CORS** — If using web clients too\n- [ ] **Test error scenarios** — Handle CometChat API failures\n\n---\n\n## 8. Monitoring and Analytics\n\n### Track CometChat Events\n\n```swift\n// Listen for connection state\nCometChat.addConnectionListener(\"connection-listener\", self)\n\nextension YourClass: CometChatConnectionDelegate {\n    func connected() {\n        Analytics.track(\"cometchat_connected\")\n    }\n    \n    func connecting() {\n        Analytics.track(\"cometchat_connecting\")\n    }\n    \n    func disconnected() {\n        Analytics.track(\"cometchat_disconnected\")\n    }\n}\n```\n\n### Track Message Events\n\n```swift\nclass AnalyticsListener: CometChatMessageEventListener {\n    \n    func ccMessageSent(message: BaseMessage, status: MessageStatus) {\n        if status == .success {\n            Analytics.track(\"message_sent\", properties: [\n                \"type\": message.messageType.rawValue,\n                \"receiver_type\": message.receiverType.rawValue\n            ])\n        }\n    }\n}\n\nCometChatMessageEvents.addListener(\"analytics\", AnalyticsListener())\n```\n\n---\n\n## 9. Common Production Issues\n\n| Issue | Cause | Solution |\n|---|---|---|\n| \"User not found\" | User not created in CometChat | Create user via REST API before login |\n| \"Invalid auth token\" | Token expired or malformed | Generate new token from server |\n| \"Rate limit exceeded\" | Too many API calls | Implement caching and rate limiting |\n| Push not working | Certificate mismatch | Verify APNs cert matches environment |\n| Calls failing | Missing SDK or permissions | Add CometChatCallsSDK and permissions |\n\n---\n\n## Summary\n\n**Development → Production Migration:**\n\n1. Remove Auth Key from iOS app\n2. Create server endpoint for token generation\n3. Update iOS app to fetch tokens from your server\n4. Create users in CometChat when they register\n5. Test thoroughly before release\n6. Monitor and handle errors gracefully","tags":["cometchat","ios","production","skills","agent-skills","ai-agent","chat","claude-code","cursor","messaging","nextjs","react"],"capabilities":["skill","source-cometchat","skill-cometchat-ios-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-ios-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 (19,444 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:53.335Z","embedding":null,"createdAt":"2026-05-07T13:05:13.381Z","updatedAt":"2026-05-18T19:04:53.335Z","lastSeenAt":"2026-05-18T19:04:53.335Z","tsv":"'-123':85,470,473,499 '/api/cometchat/token':237,355,682,1191,1230,1238 '/api/profile':1089 '/api/register':1021 '/auth_tokens':285,404,455 '/avatar.jpg':506 '/express):**':201 '/v3/users':485,1058 '/v3/users/':401,453 '/v3/users/$':283,1124 '0':1385 '1':54,137,173,242,362,1030,1100,1389,1744 '2':143,160,181,266,386,1043,1110,1415,1751 '200':422 '3':150,190,295,507,1376,1758 '4':154,993,1768 '401':262,385 '5':1140,1776 '500':312,439 '6':1304,1781 '7':1422 '8':1611 '9':1674 'abc123xyz':474,1155 'abus':1584 'add':701,1585,1736 'ai':1465,1551,1555 'alway':1179,1216 'analyt':1568,1614,1672 'analytics.track':1633,1638,1643,1662 'analyticslisten':1651,1673 'anyon':102 'api':149,184,223,226,229,278,289,343,347,396,408,442,449,460,481,490,879,948,1053,1068,1119,1131,1146,1161,1220,1443,1574,1609,1693,1713 'api-staging.yourapp.com':956 'api.yourapp.com':959,1229,1237 'api.yourapp.com/api/cometchat/token':1228,1236 'apibaseurl':951 'apikey':287,406,457,487,1066,1129,1154 'apn':1473,1540,1726 'app':73,100,106,140,197,212,216,219,276,332,336,340,394,896,966,975,978,985,988,1008,1051,1117,1158,1168,1291,1428,1453,1457,1505,1524,1750,1761 'app.post':236,1020,1190 'app.put':1088 'app.route':354 'appconfig':903 'appconfig.apibaseurl':681 'appconfig.cometchatappid':570 'appconfig.cometchatregion':573 'appconfig.swift':899 'appid':448,480,569,911,925 'application/json':294,413,465,495,696,1073,1136 'async':238,1022,1090,1193 'at':1295 'attack':110 'attempt':1384,1387,1388,1407,1416,1421 'auth':14,39,45,61,68,90,94,125,135,152,179,188,249,256,269,368,375,389,445,542,639,703,1174,1241,1343,1345,1431,1697,1746 'authent':58,174,247,366,1275,1284,1308 'authenticatemiddlewar':1192,1196 'authkey':562 'authmanager.shared.accesstoken':711 'author':716 'authtoken':300,427,430,471,654,657,710,714,753,755,760,773,782,783 'avatar':503,1063,1095,1109,1127 'await':273,1038,1048,1105,1114 'axio':208,210 'axios.post':274,1049 'axios.put':1115 'basemessag':1656 'bearer':713 'behavior':1504 'best':17,48,1142 'binari':101 'bodi':496 'bool':550 'build':575 'bundle.main.object':912,933 'cach':1716 'call':182,1481,1714,1730 'camera':1492 'capabl':1556 'case':586,599,651,660,791,801,836,843,855,857,859,861,868,875,881,889,1270,1277,1323,1342,1354,1395,1402 'catch':302,765 'caus':1679 'ccmessages':1654 'cert':1727 'certif':1474,1541,1723 'check':624 'checklist':21,53,1424 'class':521,1650 'clean':1499 'clear':1253 'client':1602 'code':421,1434 'cometchat':2,8,30,148,158,183,215,222,232,268,275,279,288,305,335,339,342,346,349,352,360,388,393,397,407,440,871,904,965,969,974,980,984,990,1012,1047,1050,1054,1067,1113,1116,1120,1130,1333,1452,1519,1608,1616,1634,1639,1644,1688,1772 'cometchat-ios-product':1 'cometchat.addconnectionlistener':1623 'cometchat.io':282,400,452,484,1057,1123 'cometchat.io/v3/users':483,1056 'cometchat.io/v3/users/':399,451 'cometchat.io/v3/users/$':281,1122 'cometchatappid':907,914,919,964 'cometchatcallssdk':1737 'cometchatconnectiondeleg':1630 'cometchaterror':853,1317 'cometchaterror.errorcode':1322 'cometchaterror.errordescription':1366 'cometchaterror.invalidresponse':764 'cometchaterror.invalidurl':686 'cometchaterror.nodata':739 'cometchaterror.notinitialized':622 'cometchatexcept':1320 'cometchatmanag':510,522,526 'cometchatmanager.shared.login':1265,1390 'cometchatmanager.shared.logout':1256 'cometchatmessageeventlisten':1652 'cometchatmessageevents.addlistener':1671 'cometchatregion':928,935,940,968 'cometchatsdk':519 'cometchatuikit':576 'cometchatuikit.getloggedinuser':595,631 'cometchatuikit.login':82,781 'cometchatuikit.logout':826 'cometchatuikitswift':517 'common':1675 'communic':1221 'complet':547,556,596,603,611,620,634,658,659,664,670,684,728,737,758,762,766,775,798,805,812,823,841,847,1377,1399,1418 'configur':897,962,1298,1441,1469,1521,1528,1550,1572,1597 'connect':1621,1625,1632,1635,1637,1640 'connection-listen':1624 'console.error':304 'const':203,207,211,214,221,231,251,271,1025,1036,1093,1097,1202 'content':292,411,463,493,699,1071,1134 'content-typ':291,410,462,492,698,1070,1133 'cor':1598 'correct':1159,1223 'cover':36 'creat':169,444,475,996,1009,1031,1044,1334,1454,1522,1686,1689,1752,1769 'createuserandretri':1341 'createuserindatabas':1039 'current':1254 'currentus':535,594,632,796,821,839 'dashboard':1459,1468,1476,1520 'data':309,423,428,429,467,720,734,735,747,885 'databas':1035,1104 'deadlin':1413 'debug':954 'debug.xcconfig':973 'decompil':104 'def':358 'default':1245,1364 'deploy':20,52,1423 'develop':38,55,59,64,75,1527,1741 'devic':1480 'direct':70 'disconnect':1642,1645 'dispatchqueue.main.async':583,788,833 'dispatchqueue.main.asyncafter':1412 'doe':502 'doesn':1329 'e.g':705 'els':431,555,619,683,736,761,822,917,938,957,1417 'email':1026,1040 'embed':97 'enabl':1460,1543,1567 'endif':960 'endpoint':168,171,1019,1754 'ensur':1294,1498 'enum':852 'environ':1578,1729 'err':1324,1344,1355 'error':264,303,307,314,383,434,551,602,605,615,663,666,674,722,726,727,730,768,779,804,807,816,846,849,851,1280,1286,1305,1309,1313,1314,1318,1368,1381,1405,1420,1512,1517,1605,1785 'error.message':310 'error.response':308 'errordescript':864 'escap':548,612,671,776,813,1378 'event':1535,1617,1648 'exampl':198,319 'example.com':505 'example.com/avatar.jpg':504 'exceed':1710 'exist':178,626,1331 'expir':1240,1246,1351,1700 'expos':1145 'express':204,206,213 'extens':1462,1545,1628 'extract':108 'f':392 'fail':315,435,1285,1731 'failur':600,604,621,661,665,685,729,738,763,767,806,848,1278,1403,1419,1610 'fals':531 'fatalerror':918,939 'featur':1466,1552 'fetch':638,1763 'fetchauthtoken':644,669 'file':972 'final':520 'flask':323,325,333 'flow':1497 'forhttpheaderfield':697,715 'forinfodictionarykey':913,934 'found':921,942,1327,1348,1683 'foundat':515,901 'friend':1516 'func':545,609,668,771,810,1251,1311,1372,1386,1631,1636,1641,1653 'generat':131,146,165,186,267,317,387,437,1187,1208,1596,1703,1757 'get':359,1262 'grace':1510,1786 'guard':553,617,676,732,818,909,930 'handl':1247,1306,1307,1507,1518,1607,1784 'handlecometchaterror':1312 'handletokenexpir':1252 'hardcod':1156 'header':286,405,417,418,456,486,704,1065,1128 'https':1215,1218 'id':217,220,277,337,341,371,380,395,403,967,976,979,986,989,1052,1118,1207 'ident':122,1178,1182 'imperson':112 'implement':509,1580,1715 'import':324,328,330,514,516,518,900 'info.plist':923,944,961,1300,1490 'init':538 'initi':540,546,874 'input':1590 'int':1375 'integr':32 'invalid':878,892,1349,1696 'invalidrespons':862,890 'invalidurl':858,876 'io':3,9,31,139,196,508,1167,1749,1760 'isiniti':530,554,591,618 'issu':1509,1677,1678 'javascript':202,1013,1087,1189 'john':501 'json':263,313,743,754 'jsonifi':326,382,426,433 'jsonserialization.jsonobject':745 'jwt':706 'jwt/session':1201 'key':40,62,69,91,95,224,227,230,290,344,348,409,461,491,543,1069,1132,1147,1162,1432,1575,1747 'let':524,565,588,601,629,653,662,677,709,725,733,742,752,793,803,819,845,906,910,927,931,950,1153,1224,1232,1279,1316,1397,1404 'limit':1559,1563,1582,1709,1719 'listen':1619,1626 'live':134,1173 'localizederror':854 'log':1357,1361,1570,1593 'logic':1370 'login':138,155,608,610,1260,1289,1695 'loginwithretri':1373 'loginwithtoken':656,772 'logout':809,811,1496 'malform':1702 'mani':1712 'mark':539,606,808,850 'match':1728 'maxattempt':1374,1408 'messag':1513,1647,1655,1663 'message.messagetype.rawvalue':1667 'message.receivertype.rawvalue':1670 'messagestatus':1658 'method':356 'microphon':1493 'middlewar':257,376 'migrat':1743 'mismatch':1724 'miss':1732 'mode':60,124 'monitor':1566,1594,1612,1782 'name':334,500,1028,1042,1061,1094,1108,1126 'navig':1287 'navigatetologin':1363 'need':478,544,1549 'network':1508 'never':77,1144,1150 'new':1263,1704 'nil':840 'nodata':860,882 'node.js':200 'node.js/express):**':199 'note':560 'notif':1471,1494,1539 'notiniti':856,869 'nsallowsarbitraryload':1303 'nsapptransportsecur':1302 'offlin':1503 'onerror':802,844 'os':331 'os.environ.get':338,345,351 'password':1027,1041 'permiss':1491,1735,1739 'plan':1562 'point':1445 'poll':1463 'post':357,447,479,694 'practic':18,49,1143 'prepar':28 'prevent':1583 'print':1272,1281 'privat':527,532,537,667,770 'problem':88 'process.env.cometchat':218,225,234 'prod':1456 'product':4,6,34,57,81,93,123,128,512,564,607,1442,1447,1451,1523,1676,1742 'production-readi':5 'profil':1081,1086 'proper':1297 'properti':1665 'provis':995 'purpos':22 'push':1470,1483,1538,1720 'python':321 'python/flask':320 'rate':1558,1581,1708,1718 're':1259,1274,1283 're-authent':1273,1282 're-login':1258 'readi':7 'real':1479 'receiv':886,1170,1668 'refer':443 'refresh':1249 'refreshtokenandretri':1353 'region':233,235,280,350,353,398,450,482,572,932,946,970,981,991,1055,1121 'regist':1775 'registr':1018 'releas':1780 'release.xcconfig':983 'remov':1430,1745 'replac':37 'req':239,1023,1091,1194 'req.body':1029,1096 'req.user.id':253,1099,1204 'request':327,329,689,719,1586 'request.httpmethod':693 'request.setvalue':695,712 'request.user.id':372 'requests.post':415 'requir':205,209,1461,1544 'res':240,1024,1092,1195 'res.json':299,1074,1137 'res.status':261,311 'respons':272,414,466,721,893 'response.data.data.authtoken':301 'response.json':424 'response.status':420 'rest':228,441,459,489,1692 'result':86,549,581,585,613,647,650,672,777,786,790,814,831,835,1266,1269,1379,1391,1394 'resum':769 'retri':1340,1369,1411 'return':151,191,260,296,381,425,432,559,623,637,687,731,740,825,870,877,883,891,924,945,955,958 'review':1489,1511,1557 'scenario':1606 'screen':1290 'sdk':159,1733 'secur':16,47,1141,1293,1573 'self':580,590,593,646,655,785,795,830,838,867,1627 'sent':1664 'separ':1455,1525 'server':12,43,117,130,142,162,167,643,888,895,1000,1016,1166,1185,1338,1437,1448,1533,1571,1707,1753,1767 'server-sid':11,42,116,161,1436,1532 'session':627,1255,1500 'set':528,533,568,571,1536,1564,1591 'setup':10 'share':525 'ship':78 'short':133,1172 'short-liv':132,1171 'showerror':1365 'side':13,44,118,163,1438,1534 'sign':1004 'simul':1488 'skill':24 'skill-cometchat-ios-production' 'solut':1680 'source-cometchat' 'state':1622 'static':523,905,926,949 'status':1657,1660 'stay':1163 'sticker':1464 'store':1429,1576 'string':673,680,749,757,774,865,908,916,929,937,952,1227,1235 'struct':902 'submit':1426 'subscribepresenceforallus':574 'success':557,587,589,592,597,598,635,652,759,792,799,824,837,842,1075,1138,1271,1276,1396,1400,1661 'summari':1740 'swift':74,513,898,1149,1160,1222,1250,1310,1371,1618,1649 'switch':584,649,789,834,866,1268,1321,1393 'system':180,250,369 'teach':25 'termin':1501 'test':1449,1477,1495,1502,1604,1777 'thorough':1778 'token':15,46,126,136,147,153,157,164,189,193,270,298,306,318,361,390,438,446,640,707,1175,1188,1209,1239,1242,1248,1264,1346,1352,1439,1595,1698,1699,1705,1756,1764 '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' 'track':1615,1646 'transport':1292 'tri':241,744 'true':558,1076,1139 'type':293,412,464,494,700,1072,1135,1666,1669 'uid':83,454,468,497,1059,1325 'uikitset':566,567,577,578 'unauthor':265,384 'understand':1560 'unknown':1367 'updat':1079,1084,1101,1111,1759 'updateuserindatabas':1106 'upload':1472,1542 'url':391,416,678,679,691,692,880,1225,1226,1233,1234,1444 'urlrequest':690 'urlsession.shared.datatask':717 'us':982,992 'use':66,1214,1217,1435,1531,1554,1600 'user':84,114,121,145,176,245,364,370,379,402,469,472,476,498,536,614,630,633,636,778,794,797,800,820,827,828,994,997,1003,1017,1032,1037,1045,1080,1083,1177,1181,1199,1206,1213,1328,1335,1359,1380,1398,1401,1515,1681,1684,1690,1770 'user-friend':1514 'user.avatarurl':1064 'user.id':1060,1078 'user.name':1062 'userid':252,259,284,1077,1098,1107,1125,1203 'valid':119,1176,1587,1588 'var':529,534,688,863,1383 'variabl':1579 'verifi':144,243,363,1180,1197,1205,1212,1725 'via':1691 'void':552,616,675,780,815,817,1382 'vs':56 'wait':1409 'weak':579,645,784,829 'web':1601 'webhook':1529 'work':1486,1722 'wrong':1148,1231 'xcconfig':971 'xml':963,1301 'yourclass':1629","prices":[{"id":"58c8f13c-ca28-41d8-8660-2a275b799c24","listingId":"ffe1bbaa-97aa-4ae5-9cca-3449a45dbbbc","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:13.381Z"}],"sources":[{"listingId":"ffe1bbaa-97aa-4ae5-9cca-3449a45dbbbc","source":"github","sourceId":"cometchat/cometchat-skills/cometchat-ios-production","sourceUrl":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-ios-production","isPrimary":false,"firstSeenAt":"2026-05-07T13:05:13.381Z","lastSeenAt":"2026-05-18T19:04:53.335Z"}],"details":{"listingId":"ffe1bbaa-97aa-4ae5-9cca-3449a45dbbbc","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cometchat","slug":"cometchat-ios-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":"dbfb9634952b4a7f396d48f404fcc7b644b97153","skill_md_path":"skills/cometchat-ios-production/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cometchat/cometchat-skills/tree/main/skills/cometchat-ios-production"},"layout":"multi","source":"github","category":"cometchat-skills","frontmatter":{"name":"cometchat-ios-production","license":"MIT","description":"Production-ready CometChat iOS setup — server-side auth tokens, security best practices, and deployment checklist.","compatibility":"CometChatUIKitSwift ^5; iOS 13+"},"skills_sh_url":"https://skills.sh/cometchat/cometchat-skills/cometchat-ios-production"},"updatedAt":"2026-05-18T19:04:53.335Z"}}