[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EMMP4GTTJCX2X1JEHEMM4W":3,"skill-same:01M6EMMP4GTTJCX2X1JEHEMM4W":66},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":32,"linkOnly":33,"markdownContent":34,"markdownBody":35,"frontMatter":36,"refName":37,"commitSha":38,"skillDirectory":39,"forksCount":40,"repositoryHtmlUrl":41,"repositoryHomepageUrl":42,"ownerHtmlUrl":43,"ownerBlogUrl":6,"ownerDescription":44,"updatedAt":45,"install":46,"resources":59},"01M6EMMP4GTTJCX2X1JEHEMM4W","pitfalls-websocket",null,"WebSocket server and client patterns with heartbeat and reconnection. Use when implementing real-time features, debugging connection issues, or reviewing WebSocket code. Triggers on: WebSocket, wss, heartbeat, reconnect, real-time.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",66,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbarissozen\u002Fpitfalls-websocket\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31],"websocket","pitfalls websocket","debugging","code","issues","server","real-time","heartbeat","use","patterns","time","triggers","client","2026-11-10 10:12:30",false,"---\nname: pitfalls-websocket\ndescription: \"WebSocket server and client patterns with heartbeat and reconnection. Use when implementing real-time features, debugging connection issues, or reviewing WebSocket code. Triggers on: WebSocket, wss, heartbeat, reconnect, real-time.\"\n---\n\n# WebSocket Pitfalls\n\nCommon pitfalls and correct patterns for WebSocket implementations.\n\n## When to Use\n\n- Implementing WebSocket server\n- Building WebSocket client with reconnection\n- Debugging connection drops\n- Adding heartbeat\u002Fping-pong\n- Reviewing WebSocket code\n\n## Workflow\n\n### Step 1: Verify Server Setup\n\nCheck WebSocket server shares HTTP port.\n\n### Step 2: Check Heartbeat\n\nEnsure ping\u002Fpong heartbeat is implemented.\n\n### Step 3: Verify Client Reconnection\n\nConfirm exponential backoff reconnection logic.\n\n---\n\n## Server Pattern\n\n```typescript\nconst wss = new WebSocketServer({ server: httpServer }); \u002F\u002F Same port\n\nwss.on('connection', (ws) => {\n  \u002F\u002F Heartbeat\n  ws.isAlive = true;\n  ws.on('pong', () => { ws.isAlive = true; });\n\n  ws.on('message', (data) => {\n    try {\n      const msg = JSON.parse(data.toString());\n      \u002F\u002F Validate message type\n    } catch {\n      ws.send(JSON.stringify({ error: 'Invalid message' }));\n    }\n  });\n});\n\n\u002F\u002F Heartbeat interval\nsetInterval(() => {\n  wss.clients.forEach((ws) => {\n    if (!ws.isAlive) return ws.terminate();\n    ws.isAlive = false;\n    ws.ping();\n  });\n}, 30000);\n```\n\n## Client Reconnection\n\n```typescript\n\u002F\u002F Client - reconnection logic with exponential backoff\nlet attempt = 0;\n\nfunction connect() {\n  const ws = new WebSocket(url);\n\n  ws.onopen = () => {\n    attempt = 0; \u002F\u002F Reset on successful connection\n  };\n\n  ws.onclose = () => {\n    const delay = Math.min(1000 * Math.pow(2, attempt), 30000);\n    attempt++;\n    setTimeout(connect, delay);\n  };\n\n  ws.onerror = (error) => {\n    console.error('WebSocket error:', error);\n  };\n}\n```\n\n## Message Handling\n\n```typescript\n\u002F\u002F ✅ Always validate and type messages\ninterface WsMessage {\n  type: 'subscribe' | 'unsubscribe' | 'ping';\n  channel?: string;\n}\n\nfunction handleMessage(ws: WebSocket, data: string) {\n  try {\n    const msg: WsMessage = JSON.parse(data);\n\n    switch (msg.type) {\n      case 'subscribe':\n        subscribeToChannel(ws, msg.channel);\n        break;\n      case 'ping':\n        ws.send(JSON.stringify({ type: 'pong' }));\n        break;\n      default:\n        ws.send(JSON.stringify({ error: 'Unknown message type' }));\n    }\n  } catch {\n    ws.send(JSON.stringify({ error: 'Invalid JSON' }));\n  }\n}\n```\n\n## Quick Checklist\n\n- [ ] WebSocket server uses same port as HTTP\n- [ ] Heartbeat ping\u002Fpong every 30 seconds\n- [ ] Client has reconnection with exponential backoff\n- [ ] Messages validated before processing\n- [ ] Connection errors logged\n","# WebSocket Pitfalls\n\nCommon pitfalls and correct patterns for WebSocket implementations.\n\n## When to Use\n\n- Implementing WebSocket server\n- Building WebSocket client with reconnection\n- Debugging connection drops\n- Adding heartbeat\u002Fping-pong\n- Reviewing WebSocket code\n\n## Workflow\n\n### Step 1: Verify Server Setup\n\nCheck WebSocket server shares HTTP port.\n\n### Step 2: Check Heartbeat\n\nEnsure ping\u002Fpong heartbeat is implemented.\n\n### Step 3: Verify Client Reconnection\n\nConfirm exponential backoff reconnection logic.\n\n---\n\n## Server Pattern\n\n```typescript\nconst wss = new WebSocketServer({ server: httpServer }); \u002F\u002F Same port\n\nwss.on('connection', (ws) => {\n  \u002F\u002F Heartbeat\n  ws.isAlive = true;\n  ws.on('pong', () => { ws.isAlive = true; });\n\n  ws.on('message', (data) => {\n    try {\n      const msg = JSON.parse(data.toString());\n      \u002F\u002F Validate message type\n    } catch {\n      ws.send(JSON.stringify({ error: 'Invalid message' }));\n    }\n  });\n});\n\n\u002F\u002F Heartbeat interval\nsetInterval(() => {\n  wss.clients.forEach((ws) => {\n    if (!ws.isAlive) return ws.terminate();\n    ws.isAlive = false;\n    ws.ping();\n  });\n}, 30000);\n```\n\n## Client Reconnection\n\n```typescript\n\u002F\u002F Client - reconnection logic with exponential backoff\nlet attempt = 0;\n\nfunction connect() {\n  const ws = new WebSocket(url);\n\n  ws.onopen = () => {\n    attempt = 0; \u002F\u002F Reset on successful connection\n  };\n\n  ws.onclose = () => {\n    const delay = Math.min(1000 * Math.pow(2, attempt), 30000);\n    attempt++;\n    setTimeout(connect, delay);\n  };\n\n  ws.onerror = (error) => {\n    console.error('WebSocket error:', error);\n  };\n}\n```\n\n## Message Handling\n\n```typescript\n\u002F\u002F ✅ Always validate and type messages\ninterface WsMessage {\n  type: 'subscribe' | 'unsubscribe' | 'ping';\n  channel?: string;\n}\n\nfunction handleMessage(ws: WebSocket, data: string) {\n  try {\n    const msg: WsMessage = JSON.parse(data);\n\n    switch (msg.type) {\n      case 'subscribe':\n        subscribeToChannel(ws, msg.channel);\n        break;\n      case 'ping':\n        ws.send(JSON.stringify({ type: 'pong' }));\n        break;\n      default:\n        ws.send(JSON.stringify({ error: 'Unknown message type' }));\n    }\n  } catch {\n    ws.send(JSON.stringify({ error: 'Invalid JSON' }));\n  }\n}\n```\n\n## Quick Checklist\n\n- [ ] WebSocket server uses same port as HTTP\n- [ ] Heartbeat ping\u002Fpong every 30 seconds\n- [ ] Client has reconnection with exponential backoff\n- [ ] Messages validated before processing\n- [ ] Connection errors logged\n",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Fbarissozen\u002Fpitfalls-websocket",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":47,"prompt":57,"zipAvailable":58},[48,51,54],{"tool":49,"command":50},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill pitfalls-websocket",{"tool":52,"command":53},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill pitfalls-websocket",{"tool":55,"command":56},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill pitfalls-websocket","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbarissozen\u002Fpitfalls-websocket\u002FSKILL.md",true,[60],{"path":61,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":64,"sourceHtmlUrl":65},"skill-report.json","REFERENCE","参考文档",8998,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fbarissozen\u002Fpitfalls-websocket\u002Fskill-report.json",[67,81,91,100,106,113],{"skillNo":68,"name":69,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":77,"publishedAt":32},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[72],{"categoryNo":73,"categoryName":74,"taxonomyType":75,"taxonomyTypeDesc":76},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[78,79,80],"model","model hierarchy","model hierarchy skill",{"skillNo":82,"name":83,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":87,"publishedAt":32},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[86],{"categoryNo":73,"categoryName":74,"taxonomyType":75,"taxonomyTypeDesc":76},[88,89,90],"MCP","zoom","zoom mcp",{"skillNo":92,"name":93,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":32},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[97,98,99,89],"sdk","zoom apps sdk","apps",{"skillNo":101,"name":102,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":32},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[102],{"skillNo":107,"name":108,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":112,"publishedAt":32},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[111],{"categoryNo":73,"categoryName":74,"taxonomyType":75,"taxonomyTypeDesc":76},[108],{"skillNo":114,"name":115,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":32},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[115]]