[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EEJM1EEPB14KS95SYMDK7X":3,"skill-same:01M6EEJM1EEPB14KS95SYMDK7X":45},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":18,"linkOnly":19,"markdownContent":20,"markdownBody":20,"frontMatter":21,"refName":22,"commitSha":23,"skillDirectory":24,"forksCount":25,"repositoryHtmlUrl":26,"repositoryHomepageUrl":27,"ownerHtmlUrl":28,"ownerBlogUrl":6,"ownerDescription":29,"updatedAt":30,"install":31,"resources":44},"01M6EEJM1EEPB14KS95SYMDK7X","centrifugo",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Fcentrifugo\u002FSKILL.md",[],[5],"2026-11-10 10:12:30",false,"# Centrifugo — Scalable Real-Time Messaging Server\n\nYou are an expert in Centrifugo, the scalable real-time messaging server. You help developers add WebSocket-based real-time features (chat, notifications, live updates, presence) to any application with a language-agnostic server that handles millions of concurrent connections — publishing from your backend via HTTP\u002FgRPC API while clients subscribe via WebSocket, SSE, or HTTP streaming.\n\n## Core Capabilities\n\n### Server Setup\n\n```bash\n# Docker\ndocker run -d --name centrifugo -p 8000:8000 \\\n  centrifugo\u002Fcentrifugo:latest centrifugo \\\n  --token_hmac_secret_key=\"your-secret\" \\\n  --api_key=\"your-api-key\" \\\n  --admin --admin_password=\"admin\" \\\n  --allowed_origins=\"*\"\n\n# Config file (config.json)\n{\n  \"token_hmac_secret_key\": \"your-256-bit-secret\",\n  \"api_key\": \"your-api-key\",\n  \"allowed_origins\": [\"https:\u002F\u002Fmyapp.com\"],\n  \"namespaces\": [\n    {\n      \"name\": \"chat\",\n      \"presence\": true,\n      \"join_leave\": true,\n      \"history_size\": 100,\n      \"history_ttl\": \"300s\",\n      \"force_recovery\": true\n    },\n    {\n      \"name\": \"notifications\",\n      \"presence\": false,\n      \"history_size\": 50,\n      \"history_ttl\": \"86400s\"\n    }\n  ]\n}\n```\n\n### Client (Browser)\n\n```typescript\nimport { Centrifuge } from \"centrifuge\";\n\nconst client = new Centrifuge(\"ws:\u002F\u002Flocalhost:8000\u002Fconnection\u002Fwebsocket\", {\n  token: userJwtToken,                     \u002F\u002F JWT signed with your secret\n});\n\n\u002F\u002F Subscribe to channel\nconst sub = client.newSubscription(\"chat:room-42\");\n\nsub.on(\"publication\", (ctx) => {\n  console.log(\"New message:\", ctx.data);   \u002F\u002F { user: \"Alice\", text: \"Hello!\" }\n});\n\nsub.on(\"join\", (ctx) => {\n  console.log(`${ctx.info.user} joined`);\n});\n\nsub.on(\"leave\", (ctx) => {\n  console.log(`${ctx.info.user} left`);\n});\n\n\u002F\u002F Presence — who's online\nconst presence = await sub.presence();\nconsole.log(\"Online users:\", Object.values(presence.clients).map(c => c.user));\n\n\u002F\u002F History — missed messages (recovery)\nconst history = await sub.history({ limit: 50 });\nhistory.publications.forEach(p => console.log(p.data));\n\nsub.subscribe();\nclient.connect();\n```\n\n### Backend Publishing\n\n```typescript\n\u002F\u002F Publish from your server via HTTP API\nasync function publishMessage(channel: string, data: any) {\n  await fetch(\"http:\u002F\u002Flocalhost:8000\u002Fapi\u002Fpublish\", {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application\u002Fjson\",\n      \"Authorization\": \"apikey your-api-key\",\n    },\n    body: JSON.stringify({ channel, data }),\n  });\n}\n\n\u002F\u002F Send chat message\nawait publishMessage(\"chat:room-42\", {\n  user: \"Alice\",\n  text: \"Hello everyone!\",\n  timestamp: Date.now(),\n});\n\n\u002F\u002F Send notification\nawait publishMessage(\"notifications:#user-123\", {\n  type: \"order_shipped\",\n  title: \"Your order has shipped!\",\n  orderId: \"ORD-456\",\n});\n\n\u002F\u002F JWT token generation (Node.js)\nimport jwt from \"jsonwebtoken\";\n\nfunction generateToken(userId: string, channels: string[]) {\n  return jwt.sign(\n    { sub: userId, channels },\n    process.env.CENTRIFUGO_SECRET!,\n    { expiresIn: \"24h\" },\n  );\n}\n```\n\n## Installation\n\n```bash\n# Server\ndocker pull centrifugo\u002Fcentrifugo\n# Or binary: https:\u002F\u002Fgithub.com\u002Fcentrifugal\u002Fcentrifugo\u002Freleases\n\n# Client SDK\nnpm install centrifuge                     # JavaScript\u002FTypeScript\n```\n\n## Best Practices\n\n1. **Server-side publish** — Clients subscribe via WebSocket; your backend publishes via HTTP API; separation of concerns\n2. **JWT authentication** — Sign tokens server-side with HMAC secret; Centrifugo validates on connect\n3. **Namespaces** — Configure per-channel behavior (presence, history, recovery); `chat:` for chat, `notifications:` for alerts\n4. **Presence** — Enable for channels where \"who's online\" matters; adds overhead, disable for broadcast-only\n5. **History recovery** — Enable `force_recovery` for chat; clients automatically catch up on reconnect\n6. **Personal channels** — Use `#user-123` pattern for per-user notifications; only that user can subscribe\n7. **Scalability** — Use Redis\u002FNats as broker for multi-node deployment; handles millions of connections\n8. **Proxy** — Configure connect\u002Fsubscribe\u002Fpublish proxies to validate permissions via your backend\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FTerminalSkills\u002Fskills\u002Fcentrifugo",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":7,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill centrifugo",{"tool":37,"command":38},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill centrifugo",{"tool":40,"command":41},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill centrifugo","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Fcentrifugo\u002FSKILL.md",true,[],[46,60,70,79,85,92],{"skillNo":47,"name":48,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":49,"categories":50,"keywords":56,"publishedAt":18},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[51],{"categoryNo":52,"categoryName":53,"taxonomyType":54,"taxonomyTypeDesc":55},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[57,58,59],"model","model hierarchy","model hierarchy skill",{"skillNo":61,"name":62,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":66,"publishedAt":18},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[65],{"categoryNo":52,"categoryName":53,"taxonomyType":54,"taxonomyTypeDesc":55},[67,68,69],"MCP","zoom","zoom mcp",{"skillNo":71,"name":72,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":18},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[76,77,78,68],"sdk","zoom apps sdk","apps",{"skillNo":80,"name":81,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":84,"publishedAt":18},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[81],{"skillNo":86,"name":87,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":91,"publishedAt":18},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[90],{"categoryNo":52,"categoryName":53,"taxonomyType":54,"taxonomyTypeDesc":55},[87],{"skillNo":93,"name":94,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":95,"categories":96,"keywords":97,"publishedAt":18},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[94]]