[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M718HNM60937AHB4434E61RB":3,"skill-same:01M718HNM60937AHB4434E61RB":152},{"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":34,"publishedAt":55,"linkOnly":56,"markdownContent":57,"markdownBody":58,"frontMatter":59,"refName":72,"commitSha":73,"skillDirectory":74,"forksCount":75,"repositoryHtmlUrl":76,"repositoryHomepageUrl":6,"ownerHtmlUrl":77,"ownerBlogUrl":78,"ownerDescription":6,"updatedAt":79,"install":80,"resources":93},"01M718HNM60937AHB4434E61RB","zoom-meeting-sdk-web",null,"Zoom Meeting SDK for Web - Embed Zoom meeting capabilities into web applications. Two integration\noptions: Client View (full-page, familiar Zoom UI) and Component View (embeddable, Promise-based API).\nIncludes SharedArrayBuffer setup for HD video, gallery view, and virtual backgrounds.","anthropics\u002Fknowledge-work-plugins","anthropics","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F76263028?v=4","01M697XGDPXJAVQ8391V2BCYTE","Anthropic","01M7188MPC48111TN566QNQE3X",35660,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002FSKILL.md",[18,23,26,29],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":27,"categoryName":28,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000016","图像与多媒体",{"categoryNo":30,"categoryName":31,"taxonomyType":32,"taxonomyTypeDesc":33},"01JBSEEDCAT000000000000034","行政与办公人员","PROFESSION","适用职业",[35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54],"web","sdk","meeting sdk","meeting","zoom","zoom meeting sdk web","for","gallery","embed","full","promise","view","virtual","Video","applications","vue","ui","capabilities","component","react","2026-11-10 10:12:30",false,"---\nname: zoom-meeting-sdk-web\ndescription: |\n  Zoom Meeting SDK for Web - Embed Zoom meeting capabilities into web applications. Two integration\n  options: Client View (full-page, familiar Zoom UI) and Component View (embeddable, Promise-based API).\n  Includes SharedArrayBuffer setup for HD video, gallery view, and virtual backgrounds.\nuser-invocable: false\ntriggers:\n  - \"embed meeting web\"\n  - \"meeting in react\"\n  - \"meeting in nextjs\"\n  - \"meeting in vue\"\n  - \"meeting in angular\"\n  - \"component view\"\n  - \"client view\"\n  - \"web meeting sdk\"\n  - \"javascript meeting\"\n  - \"sharedarraybuffer\"\n---\n\n# Zoom Meeting SDK (Web)\n\nEmbed Zoom meeting capabilities into web applications with two integration options: **Client View** (full-page) or **Component View** (embeddable).\n\n## How to Implement a Custom Video User Interface for a Zoom Meeting in a Web App\n\nUse **Meeting SDK Web Component View**.\n\nDo not use Video SDK for this question unless the user is explicitly building a non-meeting session\nproduct.\n\nMinimal architecture:\n\n```text\nBrowser page\n  -> fetch Meeting SDK signature from backend\n  -> ZoomMtgEmbedded.createClient()\n  -> client.init({ zoomAppRoot })\n  -> client.join({ signature, sdkKey, meetingNumber, userName, password })\n  -> apply layout\u002Fstyle\u002Fcustomize options around the embedded meeting container\n```\n\nMinimal implementation:\n\n```ts\nimport ZoomMtgEmbedded from '@zoom\u002Fmeetingsdk\u002Fembedded';\n\nconst client = ZoomMtgEmbedded.createClient();\n\nexport async function startEmbeddedMeeting(meetingNumber: string, userName: string, password: string) {\n  const sigRes = await fetch('\u002Fapi\u002Fsignature', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application\u002Fjson' },\n    body: JSON.stringify({ meetingNumber, role: 0 }),\n  });\n\n  if (!sigRes.ok) throw new Error(`signature_fetch_failed:${sigRes.status}`);\n\n  const { signature, sdkKey } = await sigRes.json();\n\n  await client.init({\n    zoomAppRoot: document.getElementById('meetingSDKElement')!,\n    language: 'en-US',\n    patchJsMedia: true,\n    leaveOnPageUnload: true,\n    customize: {\n      video: { isResizable: true, popper: { disableDraggable: false } },\n    },\n  });\n\n  await client.join({\n    signature,\n    sdkKey,\n    meetingNumber,\n    userName,\n    password,\n  });\n}\n```\n\nCommon failure points:\n- wrong route: Video SDK instead of Meeting SDK Component View\n- missing backend signature endpoint\n- wrong password field (`password` here, not `passWord`)\n- missing OBF\u002FZAK requirements for meetings outside the app account\n- missing SharedArrayBuffer headers when higher-end meeting features are expected\n\n## Hard Routing Rule\n\nIf the user wants a **custom video user interface for a Zoom meeting in a web app**, route to\n**Component View**, not Video SDK.\n\n- **Meeting SDK Component View** = custom UI for a real Zoom meeting\n- **Video SDK Web** = custom UI for a non-meeting video session product\n\nFor the direct custom-meeting-UI path, start with\n[component-view\u002FSKILL.md](component-view\u002FSKILL.md).\n\n## New to Web SDK? Start Here!\n\n**The fastest way to master the SDK:**\n\n1. **Choose Your View** - [Client View vs Component View](#client-view-vs-component-view) - Understand the key architectural differences\n2. **Quick Start** - [Client View](#quick-start-client-view) or [Component View](#quick-start-component-view) - Get a working meeting in minutes\n3. **SharedArrayBuffer** - [concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md) - Required for HD video, gallery view, virtual backgrounds\n4. **Optional preflight diagnostics** - [..\u002F..\u002Fprobe-sdk\u002FSKILL.md](..\u002F..\u002Fprobe-sdk\u002FSKILL.md) - Validate browser\u002Fdevice\u002Fnetwork before join\n\n**Building a Custom Integration?**\n- Component View gives you Promise-based API and embeddable UI\n- Client View gives you the familiar full-page Zoom experience\n- For a custom meeting UI, prefer **Component View** first\n- Cross-product routing example: [..\u002F..\u002Fgeneral\u002Fuse-cases\u002Fcustom-meeting-ui-web.md](..\u002F..\u002Fgeneral\u002Fuse-cases\u002Fcustom-meeting-ui-web.md)\n- [Browser Support](concepts\u002Fbrowser-support.md) - Feature matrix by browser\n- Exact deep-dive path: [component-view\u002FSKILL.md](component-view\u002FSKILL.md)\n\n**Having issues?**\n- Join errors → Check signature generation and password spelling (`passWord` vs `password`)\n- HD video not working → Enable SharedArrayBuffer headers\n- Complete navigation → [SKILL.md](SKILL.md)\n\n## Prerequisites\n\n- Zoom app with Meeting SDK credentials from [Marketplace](https:\u002F\u002Fmarketplace.zoom.us\u002F)\n- SDK Key (Client ID) and Secret\n- Modern browser (Chrome, Firefox, Safari, Edge)\n- Backend auth endpoint for signature generation\n\n> **Need help with authentication?** See the **[zoom-oauth](..\u002F..\u002Foauth\u002FSKILL.md)** skill for JWT\u002Fsignature generation.\n>\n> **Want pre-join diagnostics?** Chain **[probe-sdk](..\u002F..\u002Fprobe-sdk\u002FSKILL.md)** before `init()`\u002F`join()` to gate low-readiness environments.\n\n## Optional Preflight Gate (Probe SDK)\n\nFor unstable first-join environments, run Probe SDK checks before calling `ZoomMtg.init()` or `client.join()`:\n\n1. Run Probe permissions\u002Fdevice\u002Fnetwork diagnostics.\n2. Apply readiness policy (`allow`, `warn`, `block`).\n3. Continue to Meeting SDK join only for `allow`\u002Fapproved `warn`.\n\nSee [..\u002F..\u002Fprobe-sdk\u002FSKILL.md](..\u002F..\u002Fprobe-sdk\u002FSKILL.md) and [..\u002F..\u002Fgeneral\u002Fuse-cases\u002Fprobe-sdk-preflight-readiness-gate.md](..\u002F..\u002Fgeneral\u002Fuse-cases\u002Fprobe-sdk-preflight-readiness-gate.md).\n\n## Client View vs Component View\n\n**CRITICAL DIFFERENCE**: These are two completely different APIs with different patterns!\n\n| Aspect | Client View | Component View |\n|--------|-------------|----------------|\n| **Object** | `ZoomMtg` (global singleton) | `ZoomMtgEmbedded.createClient()` (instance) |\n| **API Style** | Callbacks | Promises |\n| **UI** | Full-page takeover | Embeddable in any container |\n| **Password param** | `passWord` (capital W) | `password` (lowercase) |\n| **Events** | `inMeetingServiceListener()` | `on()`\u002F`off()` |\n| **Import (npm)** | `import { ZoomMtg } from '@zoom\u002Fmeetingsdk'` | `import ZoomMtgEmbedded from '@zoom\u002Fmeetingsdk\u002Fembedded'` |\n| **CDN** | `zoom-meeting-{VERSION}.min.js` | `zoom-meeting-embedded-{VERSION}.min.js` |\n| **Best For** | Quick integration, standard Zoom UI | Custom layouts, React\u002FVue apps |\n\n### When to Use Which\n\n**Use Client View when:**\n- You want the familiar Zoom meeting interface\n- Quick integration is priority over customization\n- Full-page meeting experience is acceptable\n\n**Use Component View when:**\n- You need to embed meetings in a specific area of your page\n- Building React\u002FVue\u002FAngular applications\n- You want Promise-based async\u002Fawait syntax\n- Custom positioning and resizing is required\n\n## Installation\n\n### NPM (Recommended)\n\n```bash\nnpm install @zoom\u002Fmeetingsdk --save\n```\n\n### CDN\n\n```html\n\u003C!-- Dependencies (required for both views) -->\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Freact.min.js\">\u003C\u002Fscript>\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Freact-dom.min.js\">\u003C\u002Fscript>\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Fredux.min.js\">\u003C\u002Fscript>\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Fredux-thunk.min.js\">\u003C\u002Fscript>\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Flodash.min.js\">\u003C\u002Fscript>\n\n\u003C!-- Client View -->\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002Fzoom-meeting-{VERSION}.min.js\">\u003C\u002Fscript>\n\n\u003C!-- OR Component View -->\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002Fzoom-meeting-embedded-{VERSION}.min.js\">\u003C\u002Fscript>\n```\n\nReplace `{VERSION}` with the [latest version](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@zoom\u002Fmeetingsdk) (e.g., `3.11.0`).\n\n## Quick Start (Client View)\n\n```javascript\nimport { ZoomMtg } from '@zoom\u002Fmeetingsdk';\n\n\u002F\u002F Step 1: Check browser compatibility\nconsole.log('System requirements:', ZoomMtg.checkSystemRequirements());\n\n\u002F\u002F Step 2: Preload WebAssembly for faster initialization\nZoomMtg.preLoadWasm();\nZoomMtg.prepareWebSDK();\n\n\u002F\u002F Step 3: Load language files (MUST complete before init)\nZoomMtg.i18n.load('en-US');\nZoomMtg.i18n.onLoad(() => {\n  \n  \u002F\u002F Step 4: Initialize SDK\n  ZoomMtg.init({\n    leaveUrl: 'https:\u002F\u002Fyoursite.com\u002Fmeeting-ended',\n    disableCORP: !window.crossOriginIsolated, \u002F\u002F Auto-detect SharedArrayBuffer\n    patchJsMedia: true,           \u002F\u002F Auto-apply media dependency fixes\n    leaveOnPageUnload: true,      \u002F\u002F Clean up when page unloads\n    externalLinkPage: '.\u002Fexternal.html', \u002F\u002F Page for external links\n    success: () => {\n      \n      \u002F\u002F Step 5: Join meeting (note: passWord with capital W!)\n      ZoomMtg.join({\n        signature: signature,       \u002F\u002F From your auth endpoint\n        meetingNumber: '1234567890',\n        userName: 'User Name',\n        passWord: 'meeting-password', \u002F\u002F Capital W!\n        success: (res) => {\n          console.log('Joined meeting:', res);\n          \n          \u002F\u002F Post-join: Get meeting info\n          ZoomMtg.getAttendeeslist({});\n          ZoomMtg.getCurrentUser({\n            success: (res) => console.log('Current user:', res.result.currentUser)\n          });\n        },\n        error: (err) => {\n          console.error('Join error:', err);\n        }\n      });\n    },\n    error: (err) => {\n      console.error('Init error:', err);\n    }\n  });\n});\n```\n\n## Quick Start (Component View)\n\n```javascript\nimport ZoomMtgEmbedded from '@zoom\u002Fmeetingsdk\u002Fembedded';\n\n\u002F\u002F Create client instance (do this ONCE, not on every render!)\nconst client = ZoomMtgEmbedded.createClient();\n\nasync function startMeeting() {\n  try {\n    \u002F\u002F Initialize with container element\n    await client.init({\n      zoomAppRoot: document.getElementById('meetingSDKElement'),\n      language: 'en-US',\n      debug: true,                  \u002F\u002F Enable debug logging\n      patchJsMedia: true,           \u002F\u002F Auto-apply media fixes\n      leaveOnPageUnload: true,      \u002F\u002F Clean up on page unload\n    });\n\n    \u002F\u002F Join meeting (note: password lowercase!)\n    await client.join({\n      signature: signature,          \u002F\u002F From your auth endpoint\n      sdkKey: SDK_KEY,\n      meetingNumber: '1234567890',\n      userName: 'User Name',\n      password: 'meeting-password',  \u002F\u002F Lowercase!\n    });\n    \n    console.log('Joined successfully!');\n  } catch (error) {\n    console.error('Failed to join:', error);\n  }\n}\n```\n\n## Authentication Endpoint (Required)\n\nBoth views require a JWT signature from a backend server. **Never expose your SDK Secret in frontend code!**\n\n```bash\n# Clone Zoom's official auth endpoint\ngit clone https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-auth-endpoint-sample --depth 1\ncd meetingsdk-auth-endpoint-sample\ncp .env.example .env\n# Edit .env with your SDK Key and Secret\nnpm install && npm run start\n```\n\n### Signature Generation\n\nThe signature encodes:\n- `sdkKey` (or `clientId` for newer apps)\n- `meetingNumber`\n- `role` (0 = participant, 1 = host)\n- `iat` (issued at timestamp)\n- `exp` (expiration timestamp)\n- `tokenExp` (token expiration)\n\n> **IMPORTANT (March 2026)**: Apps joining meetings outside their account will require an App Privilege Token (OBF) or ZAK token. See [Authorization Requirements](#authorization-requirements-2026-update).\n\n## Core Workflow\n\n```\n┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐\n│   Get Signature │───►│   init()        │───►│   join()        │\n│   (from backend)│    │   (SDK setup)   │    │   (enter mtg)   │\n└─────────────────┘    └─────────────────┘    └─────────────────┘\n                              │                       │\n                              ▼                       ▼\n                       success\u002Ferror            success\u002Ferror\n                        callback                 callback\n                     (or Promise resolve)    (or Promise resolve)\n```\n\n## Client View API Reference\n\n### ZoomMtg.init() - Key Options\n\n```javascript\nZoomMtg.init({\n  \u002F\u002F Required\n  leaveUrl: string,              \u002F\u002F URL to redirect after leaving\n\n  \u002F\u002F Display Options\n  showMeetingHeader: boolean,    \u002F\u002F Show meeting number\u002Ftopic (default: true)\n  disableInvite: boolean,        \u002F\u002F Hide invite button (default: false)\n  disableRecord: boolean,        \u002F\u002F Hide record button (default: false)\n  disableJoinAudio: boolean,     \u002F\u002F Hide join audio option (default: false)\n  disablePreview: boolean,       \u002F\u002F Skip A\u002FV preview (default: false)\n  \n  \u002F\u002F HD Video (requires SharedArrayBuffer)\n  enableHD: boolean,             \u002F\u002F Enable 720p (default: true for >=2.8.0)\n  enableFullHD: boolean,         \u002F\u002F Enable 1080p for webinars (default: false)\n  \n  \u002F\u002F View Options\n  defaultView: 'gallery' | 'speaker' | 'multiSpeaker',\n  \n  \u002F\u002F Feature Toggles\n  isSupportChat: boolean,        \u002F\u002F Enable chat (default: true)\n  isSupportCC: boolean,          \u002F\u002F Enable closed captions (default: true)\n  isSupportBreakout: boolean,    \u002F\u002F Enable breakout rooms (default: true)\n  isSupportPolling: boolean,     \u002F\u002F Enable polling (default: true)\n  isSupportQA: boolean,          \u002F\u002F Enable Q&A for webinars (default: true)\n  \n  \u002F\u002F Cross-Origin\n  disableCORP: boolean,          \u002F\u002F For dev without COOP\u002FCOEP headers\n  \n  \u002F\u002F Callbacks\n  success: Function,\n  error: Function,\n});\n```\n\n### ZoomMtg.join() - Key Options\n\n```javascript\nZoomMtg.join({\n  \u002F\u002F Required\n  signature: string,             \u002F\u002F JWT signature from backend\n  meetingNumber: string | number,\n  userName: string,\n  \n  \u002F\u002F Authentication\n  passWord: string,              \u002F\u002F Meeting password (capital W!)\n  zak: string,                   \u002F\u002F Host's ZAK token (required to start)\n  tk: string,                    \u002F\u002F Registration token (if required)\n  obfToken: string,              \u002F\u002F App Privilege Token (for 2026 requirement)\n  \n  \u002F\u002F Optional\n  userEmail: string,             \u002F\u002F Required for webinars\n  customerKey: string,           \u002F\u002F Custom identifier (max 36 chars)\n  \n  \u002F\u002F Callbacks\n  success: Function,\n  error: Function,\n});\n```\n\n### Event Listeners (Client View)\n\n```javascript\n\u002F\u002F User events\nZoomMtg.inMeetingServiceListener('onUserJoin', (data) => {\n  console.log('User joined:', data);\n});\n\nZoomMtg.inMeetingServiceListener('onUserLeave', (data) => {\n  console.log('User left:', data);\n  \u002F\u002F data.reasonCode values:\n  \u002F\u002F 0: OTHER\n  \u002F\u002F 1: HOST_ENDED_MEETING\n  \u002F\u002F 2: SELF_LEAVE_FROM_IN_MEETING\n  \u002F\u002F 3: SELF_LEAVE_FROM_WAITING_ROOM\n  \u002F\u002F 4: SELF_LEAVE_FROM_WAITING_FOR_HOST_START\n  \u002F\u002F 5: MEETING_TRANSFER\n  \u002F\u002F 6: KICK_OUT_FROM_MEETING\n  \u002F\u002F 7: KICK_OUT_FROM_WAITING_ROOM\n  \u002F\u002F 8: LEAVE_FROM_DISCLAIMER\n});\n\nZoomMtg.inMeetingServiceListener('onUserUpdate', (data) => {\n  console.log('User updated:', data);\n});\n\n\u002F\u002F Meeting status\nZoomMtg.inMeetingServiceListener('onMeetingStatus', (data) => {\n  \u002F\u002F status: 1=connecting, 2=connected, 3=disconnected, 4=reconnecting\n  console.log('Meeting status:', data.status);\n});\n\n\u002F\u002F Waiting room\nZoomMtg.inMeetingServiceListener('onUserIsInWaitingRoom', (data) => {\n  console.log('User in waiting room:', data);\n});\n\n\u002F\u002F Active speaker detection\nZoomMtg.inMeetingServiceListener('onActiveSpeaker', (data) => {\n  \u002F\u002F [{userId: number, userName: string}]\n  console.log('Active speaker:', data);\n});\n\n\u002F\u002F Network quality monitoring\nZoomMtg.inMeetingServiceListener('onNetworkQualityChange', (data) => {\n  \u002F\u002F {level: 0-5, userId, type: 'uplink'}\n  \u002F\u002F 0-1 = bad, 2 = normal, 3-5 = good\n  if (data.level \u003C= 1) {\n    console.warn('Poor network quality');\n  }\n});\n\n\u002F\u002F Join performance metrics\nZoomMtg.inMeetingServiceListener('onJoinSpeed', (data) => {\n  console.log('Join speed metrics:', data);\n  \u002F\u002F Useful for performance monitoring dashboards\n});\n\n\u002F\u002F Chat\nZoomMtg.inMeetingServiceListener('onReceiveChatMsg', (data) => {\n  console.log('Chat message:', data);\n});\n\n\u002F\u002F Recording\nZoomMtg.inMeetingServiceListener('onRecordingChange', (data) => {\n  console.log('Recording status:', data);\n});\n\n\u002F\u002F Screen sharing\nZoomMtg.inMeetingServiceListener('onShareContentChange', (data) => {\n  console.log('Share content changed:', data);\n});\n\n\u002F\u002F Transcription (requires \"save closed captions\" enabled)\nZoomMtg.inMeetingServiceListener('onReceiveTranscriptionMsg', (data) => {\n  console.log('Transcription:', data);\n});\n\n\u002F\u002F Breakout room status\nZoomMtg.inMeetingServiceListener('onRoomStatusChange', (data) => {\n  \u002F\u002F status: 2=InProgress, 3=Closing, 4=Closed\n  console.log('Breakout room status:', data);\n});\n```\n\n### Common Methods (Client View)\n\n```javascript\n\u002F\u002F Get current user info\nZoomMtg.getCurrentUser({\n  success: (res) => console.log(res.result.currentUser)\n});\n\n\u002F\u002F Get all attendees\nZoomMtg.getAttendeeslist({});\n\n\u002F\u002F Audio\u002FVideo control\nZoomMtg.mute({ userId, mute: true });\nZoomMtg.muteAll({ muteAll: true });\n\n\u002F\u002F Chat\nZoomMtg.sendChat({ message: 'Hello!', userId: 0 }); \u002F\u002F 0 = everyone\n\n\u002F\u002F Leave\u002FEnd\nZoomMtg.leaveMeeting({});\nZoomMtg.endMeeting({});\n\n\u002F\u002F Host controls\nZoomMtg.makeHost({ userId });\nZoomMtg.makeCoHost({ oderId });\nZoomMtg.expel({ userId });  \u002F\u002F Remove participant\nZoomMtg.putOnHold({ oderId, bHold: true });\n\n\u002F\u002F Breakout rooms\nZoomMtg.createBreakoutRoom({ rooms: [...] });\nZoomMtg.openBreakoutRooms({});\nZoomMtg.closeBreakoutRooms({});\n\n\u002F\u002F Virtual background\nZoomMtg.setVirtualBackground({ imageUrl: '...' });\n```\n\n## Component View API Reference\n\n### client.init() - Key Options\n\n```javascript\nawait client.init({\n  \u002F\u002F Required\n  zoomAppRoot: HTMLElement,      \u002F\u002F Container element\n\n  \u002F\u002F Display\n  language: string,              \u002F\u002F e.g., 'en-US'\n  debug: boolean,                \u002F\u002F Enable debug logging (default: false)\n  \n  \u002F\u002F Media\n  patchJsMedia: boolean,         \u002F\u002F Auto-apply media fixes (default: false)\n  leaveOnPageUnload: boolean,    \u002F\u002F Clean up on page unload (default: false)\n  \n  \u002F\u002F Video\n  enableHD: boolean,             \u002F\u002F Enable 720p\n  enableFullHD: boolean,         \u002F\u002F Enable 1080p\n  \n  \u002F\u002F Customization\n  customize: {\n    video: {\n      isResizable: boolean,\n      viewSizes: { default: { width, height } }\n    },\n    meetingInfo: ['topic', 'host', 'mn', 'pwd', 'telPwd', 'invite', 'participant', 'dc', 'enctype'],\n    toolbar: {\n      buttons: [\n        {\n          text: 'Custom Button',\n          className: 'custom-btn',\n          onClick: () => {\n            console.log('Custom button clicked');\n          }\n        }\n      ]\n    }\n  },\n  \n  \u002F\u002F For ZFG\n  webEndpoint: string,\n  assetPath: string,             \u002F\u002F Custom path for AV libraries (self-hosting)\n});\n```\n\n### client.join() - Key Options\n\n```javascript\nawait client.join({\n  \u002F\u002F Required\n  signature: string,\n  sdkKey: string,\n  meetingNumber: string | number,\n  userName: string,\n  \n  \u002F\u002F Authentication  \n  password: string,              \u002F\u002F Lowercase! (different from Client View)\n  zak: string,                   \u002F\u002F Host's ZAK token\n  tk: string,                    \u002F\u002F Registration token\n  \n  \u002F\u002F Optional\n  userEmail: string,\n});\n```\n\n### Event Listeners (Component View)\n\n```javascript\n\u002F\u002F Connection state\nclient.on('connection-change', (payload) => {\n  \u002F\u002F payload.state: 'Connecting', 'Connected', 'Reconnecting', 'Closed'\n  console.log('Connection:', payload.state);\n});\n\n\u002F\u002F User events\nclient.on('user-added', (payload) => {\n  console.log('Users added:', payload);\n});\n\nclient.on('user-removed', (payload) => {\n  console.log('Users removed:', payload);\n});\n\nclient.on('user-updated', (payload) => {\n  console.log('Users updated:', payload);\n});\n\n\u002F\u002F Active speaker\nclient.on('active-speaker', (payload) => {\n  console.log('Active speaker:', payload);\n});\n\n\u002F\u002F Video state\nclient.on('video-active-change', (payload) => {\n  console.log('Video active:', payload);\n});\n\n\u002F\u002F Unsubscribe\nclient.off('connection-change', handler);\n```\n\n### Common Methods (Component View)\n\n```javascript\n\u002F\u002F Get current user\nconst currentUser = client.getCurrentUser();\n\n\u002F\u002F Get all participants\nconst participants = client.getParticipantsList();\n\n\u002F\u002F Audio control\nawait client.mute(true);\nawait client.muteAudio(userId, true);\n\n\u002F\u002F Video control\nawait client.muteVideo(userId, true);\n\n\u002F\u002F Leave\nclient.leaveMeeting();\n\n\u002F\u002F End (host only)\nclient.endMeeting();\n```\n\n## SharedArrayBuffer (CRITICAL for HD)\n\nSharedArrayBuffer enables advanced features:\n- 720p\u002F1080p video\n- Gallery view\n- Virtual backgrounds\n- Background noise suppression\n\n### Enable with HTTP Headers\n\n```\nCross-Origin-Opener-Policy: same-origin\nCross-Origin-Embedder-Policy: require-corp\n```\n\n### Verify in Browser\n\n```javascript\nif (typeof SharedArrayBuffer === 'function') {\n  console.log('SharedArrayBuffer enabled!');\n} else {\n  console.warn('HD features will be limited');\n}\n\n\u002F\u002F Or check cross-origin isolation\nconsole.log('Cross-origin isolated:', window.crossOriginIsolated);\n```\n\n### Platform-Specific Setup\n\nSee [concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md) for:\n- Vercel, Netlify, AWS CloudFront configuration\n- nginx\u002FApache configuration\n- Service worker fallback for GitHub Pages\n\n### Development Setup (Two-Server Pattern)\n\nThe official samples use a **two-server pattern** for development because COOP\u002FCOEP headers can break navigation:\n\n```javascript\n\u002F\u002F Server 1: Main app (port 9999) - NO isolation headers\n\u002F\u002F Serves index.html, navigation works normally\n\n\u002F\u002F Server 2: Meeting page (port 9998) - WITH isolation headers\n\u002F\u002F Serves meeting.html with SharedArrayBuffer support\n\n\u002F\u002F Main server proxies to meeting server\nproxy: [{\n  path: '\u002Fmeeting.html',\n  target: 'http:\u002F\u002FYOUR_MEETING_SERVER_HOST:9998\u002F'\n}]\n```\n\n**Vite config with headers:**\n```typescript\n\u002F\u002F vite.config.ts\nexport default defineConfig({\n  server: {\n    headers: {\n      'Cross-Origin-Embedder-Policy': 'require-corp',\n      'Cross-Origin-Opener-Policy': 'same-origin',\n    }\n  }\n});\n```\n\n## Common Issues & Solutions\n\n| Issue | Solution |\n|-------|----------|\n| **Join fails with signature error** | Verify signature generation, check sdkKey format |\n| **\"passWord\" typo** | Client View uses `passWord` (capital W), Component View uses `password` |\n| **No HD video** | Enable SharedArrayBuffer headers, check browser support |\n| **Callbacks not firing** | Ensure `inMeetingServiceListener` called after init success |\n| **Virtual background not working** | Requires SharedArrayBuffer + Chrome\u002FEdge |\n| **Screen share fails on Safari** | Safari 17+ with macOS 14+ required for client view |\n\n**Complete troubleshooting**: [troubleshooting\u002Fcommon-issues.md](troubleshooting\u002Fcommon-issues.md)\n\n## Browser Support Matrix\n\n| Feature | Chrome | Firefox | Safari | Edge | iOS | Android |\n|---------|--------|---------|--------|------|-----|---------|\n| 720p (receive) | Yes | Yes | Yes | Yes | Yes | Yes |\n| 720p (send) | Yes* | Yes* | Yes* | Yes* | Yes* | Yes* |\n| Virtual background | Yes | Yes | No | Yes | No | No |\n| Screen share (send) | Yes | Yes | Safari 17+ | Yes | No | No |\n| Gallery view | Yes | Yes | Yes** | Yes | Yes | Yes |\n\n*Requires SharedArrayBuffer\n**Safari 17+ with macOS Sonoma\n\nSee [concepts\u002Fbrowser-support.md](concepts\u002Fbrowser-support.md) for complete matrix.\n\n## Authorization Requirements (2026 Update)\n\n> **IMPORTANT**: Beginning **March 2, 2026**, apps joining meetings outside their account must be authorized.\n\n### Options\n\n1. **App Privilege Token (OBF)** - Recommended for bots\n   ```javascript\n   ZoomMtg.join({\n     ...\n     obfToken: 'your-app-privilege-token'\n   });\n   ```\n\n2. **ZAK Token** - For host operations\n   ```javascript\n   ZoomMtg.join({\n     ...\n     zak: 'host-zak-token'\n   });\n   ```\n\n## Zoom for Government (ZFG)\n\n### Option 1: ZFG-specific NPM Package\n\n```json\n{\n  \"dependencies\": {\n    \"@zoom\u002Fmeetingsdk\": \"3.11.2-zfg\"\n  }\n}\n```\n\n### Option 2: Configure ZFG Endpoints\n\n**Client View:**\n```javascript\nZoomMtg.setZoomJSLib('https:\u002F\u002Fsource.zoomgov.com\u002F{VERSION}\u002Flib', '\u002Fav');\nZoomMtg.init({\n  webEndpoint: 'www.zoomgov.com',\n  ...\n});\n```\n\n**Component View:**\n```javascript\nawait client.init({\n  webEndpoint: 'www.zoomgov.com',\n  assetPath: 'https:\u002F\u002Fsource.zoomgov.com\u002F{VERSION}\u002Flib\u002Fav',\n  ...\n});\n```\n\n## China CDN\n\n```javascript\n\u002F\u002F Set before preLoadWasm()\nZoomMtg.setZoomJSLib('https:\u002F\u002Fjssdk.zoomus.cn\u002F{VERSION}\u002Flib', '\u002Fav');\n```\n\n## React Integration\n\n### Official Pattern (from zoom\u002Fmeetingsdk-react-sample)\n\nThe official React sample uses **imperative initialization** rather than React hooks:\n\n```tsx\nimport { ZoomMtg } from '@zoom\u002Fmeetingsdk';\n\n\u002F\u002F Preload at module level (outside component)\nZoomMtg.preLoadWasm();\nZoomMtg.prepareWebSDK();\n\nfunction App() {\n  const authEndpoint = import.meta.env.VITE_AUTH_ENDPOINT;\n  const meetingNumber = '';\n  const passWord = '';\n  const role = 0;\n  const userName = 'React User';\n\n  const getSignature = async () => {\n    const response = await fetch(authEndpoint, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application\u002Fjson' },\n      body: JSON.stringify({\n        meetingNumber,\n        role,\n      }),\n    });\n    const data = await response.json();\n    startMeeting(data.signature);\n  };\n\n  const startMeeting = (signature: string) => {\n    document.getElementById('zmmtg-root')!.style.display = 'block';\n\n    ZoomMtg.init({\n      leaveUrl: window.location.origin,\n      patchJsMedia: true,\n      leaveOnPageUnload: true,\n      success: () => {\n        ZoomMtg.join({\n          signature,\n          meetingNumber,\n          userName,\n          passWord,\n          success: (res) => console.log('Joined:', res),\n          error: (err) => console.error('Join error:', err),\n        });\n      },\n      error: (err) => console.error('Init error:', err),\n    });\n  };\n\n  return (\n    \u003Cbutton onClick={getSignature}>Join Meeting\u003C\u002Fbutton>\n  );\n}\n```\n\n### React Gotchas (from official samples)\n\n| Issue | Problem | Solution |\n|-------|---------|----------|\n| **Client Recreation** | `createClient()` in component body runs every render | Use `useRef` to persist client |\n| **No useEffect** | Official sample doesn't use React lifecycle hooks | SDK's `leaveOnPageUnload` handles cleanup |\n| **Direct DOM** | Sample uses `getElementById` | Use `useRef\u003CHTMLDivElement>` in production |\n| **No Error State** | Silent failures | Add `useState` for error handling |\n| **Module-Scope Side Effects** | `preLoadWasm()` at top level | May cause issues with SSR |\n\n### Production-Ready React Pattern\n\n```tsx\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport ZoomMtgEmbedded from '@zoom\u002Fmeetingsdk\u002Fembedded';\n\ntype ZoomClient = ReturnType\u003Ctypeof ZoomMtgEmbedded.createClient>;\n\nfunction ZoomMeeting({ meetingNumber, password, userName }: Props) {\n  const clientRef = useRef\u003CZoomClient | null>(null);\n  const containerRef = useRef\u003CHTMLDivElement>(null);\n  const [isJoining, setIsJoining] = useState(false);\n  const [error, setError] = useState\u003Cstring | null>(null);\n\n  \u002F\u002F Create client once\n  useEffect(() => {\n    if (!clientRef.current) {\n      clientRef.current = ZoomMtgEmbedded.createClient();\n    }\n  }, []);\n\n  const joinMeeting = useCallback(async () => {\n    if (!clientRef.current || !containerRef.current) return;\n    \n    setIsJoining(true);\n    setError(null);\n\n    try {\n      \u002F\u002F Get signature from your backend\n      const response = await fetch('\u002Fapi\u002Fsignature', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application\u002Fjson' },\n        body: JSON.stringify({ meetingNumber, role: 0 }),\n      });\n      const { signature, sdkKey } = await response.json();\n      \n      await clientRef.current.init({\n        zoomAppRoot: containerRef.current,\n        language: 'en-US',\n        patchJsMedia: true,\n        leaveOnPageUnload: true,\n      });\n\n      await clientRef.current.join({\n        signature,\n        sdkKey,\n        meetingNumber,\n        password,\n        userName,\n      });\n    } catch (err) {\n      setError(err instanceof Error ? err.message : 'Failed to join');\n    } finally {\n      setIsJoining(false);\n    }\n  }, [meetingNumber, password, userName]);\n\n  return (\n    \u003Cdiv>\n      \u003Cdiv ref={containerRef} style={{ width: '100%', height: '500px' }} \u002F>\n      \u003Cbutton onClick={joinMeeting} disabled={isJoining}>\n        {isJoining ? 'Joining...' : 'Join Meeting'}\n      \u003C\u002Fbutton>\n      {error && \u003Cdiv className=\"error\">{error}\u003C\u002Fdiv>}\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n### Environment Variables (Vite)\n\n```bash\n# .env.local\nVITE_AUTH_ENDPOINT=http:\u002F\u002FYOUR_AUTH_SERVER_HOST:4000\nVITE_SDK_KEY=your_sdk_key\n```\n\n```tsx\nconst authEndpoint = import.meta.env.VITE_AUTH_ENDPOINT;\nconst sdkKey = import.meta.env.VITE_SDK_KEY;\n```\n\n## Detailed References\n\n### Core Documentation\n- **[SKILL.md](SKILL.md)** - Complete navigation guide\n- **[client-view\u002FSKILL.md](client-view\u002FSKILL.md)** - Full Client View reference\n- **[component-view\u002FSKILL.md](component-view\u002FSKILL.md)** - Full Component View reference\n\n### Concepts\n- **[concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md)** - HD video requirements\n- **[concepts\u002Fbrowser-support.md](concepts\u002Fbrowser-support.md)** - Feature matrix by browser\n\n### Troubleshooting\n- **[troubleshooting\u002Ferror-codes.md](troubleshooting\u002Ferror-codes.md)** - All SDK error codes\n- **[troubleshooting\u002Fcommon-issues.md](troubleshooting\u002Fcommon-issues.md)** - Quick diagnostics\n\n### Examples\n- **[client-view\u002FSKILL.md](client-view\u002FSKILL.md)** - Complete Client View guide\n- **[component-view\u002FSKILL.md](component-view\u002FSKILL.md)** - Component View React integration\n\n## Helper Utilities\n\n### Extract Meeting Number from Invite Link\n\n```javascript\n\u002F\u002F Users can paste full Zoom invite links\ndocument.getElementById('meeting_number').addEventListener('input', (e) => {\n  \u002F\u002F Extract meeting number (9-11 digits)\n  let meetingNumber = e.target.value.replace(\u002F([^0-9])+\u002Fi, '');\n  if (meetingNumber.match(\u002F([0-9]{9,11})\u002F)) {\n    meetingNumber = meetingNumber.match(\u002F([0-9]{9,11})\u002F)[1];\n  }\n  \n  \u002F\u002F Auto-extract password from invite link\n  const pwdMatch = e.target.value.match(\u002Fpwd=([\\d,\\w]+)\u002F);\n  if (pwdMatch) {\n    document.getElementById('password').value = pwdMatch[1];\n  }\n});\n```\n\n### Dynamic Language Switching\n\n```javascript\n\u002F\u002F Change language at runtime\ndocument.getElementById('language').addEventListener('change', (e) => {\n  const lang = e.target.value;\n  ZoomMtg.i18n.load(lang);\n  ZoomMtg.i18n.reload(lang);\n  ZoomMtg.reRender({ lang });\n});\n```\n\n### Check System Requirements\n\n```javascript\n\u002F\u002F Check browser compatibility before initializing\nconst requirements = ZoomMtg.checkSystemRequirements();\nconsole.log('Browser info:', JSON.stringify(requirements));\n\nif (!requirements.browserInfo.isChrome && !requirements.browserInfo.isFirefox) {\n  alert('For best experience, use Chrome or Firefox');\n}\n```\n\n## Sample Repositories\n\n| Repository | Description |\n|------------|-------------|\n| [meetingsdk-web-sample](https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-web-sample) | Official samples (Client View & Component View) |\n| [meetingsdk-react-sample](https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-react-sample) | React integration with TypeScript + Vite |\n| [meetingsdk-web](https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-web) | SDK source with helper.html |\n| [meetingsdk-auth-endpoint-sample](https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-auth-endpoint-sample) | Signature generation backend |\n\n## Official Resources\n\n- **Official docs**: https:\u002F\u002Fdevelopers.zoom.us\u002Fdocs\u002Fmeeting-sdk\u002Fweb\u002F\n- **Client View API Reference**: https:\u002F\u002Fmarketplacefront.zoom.us\u002Fsdk\u002Fmeeting\u002Fweb\u002Findex.html\n- **Component View API Reference**: https:\u002F\u002Fmarketplacefront.zoom.us\u002Fsdk\u002Fmeeting\u002Fweb\u002Fcomponents\u002Findex.html\n- **Developer forum**: https:\u002F\u002Fdevforum.zoom.us\u002F\n\n---\n\n**Documentation Version**: Based on Zoom Web Meeting SDK v3.11+\n\n**Need help?** Start with [SKILL.md](SKILL.md) for complete navigation.\n\n\n## Merged from meeting-sdk\u002Fweb\u002FSKILL.md\n\n# Zoom Meeting SDK (Web) - Documentation Index\n\nQuick navigation guide for all Web SDK documentation.\n\n## Start Here\n\n| Document | Description |\n|----------|-------------|\n| **[SKILL.md](SKILL.md)** | Main entry point - Quick starts for both Client View and Component View |\n\n## By View Type\n\n### Client View (Full-Page)\n| Document | Description |\n|----------|-------------|\n| **[client-view\u002FSKILL.md](client-view\u002FSKILL.md)** | Complete Client View reference |\n\n### Component View (Embeddable)\n| Document | Description |\n|----------|-------------|\n| **[component-view\u002FSKILL.md](component-view\u002FSKILL.md)** | Complete Component View reference |\n\n## Concepts\n\n| Document | Description |\n|----------|-------------|\n| **[concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md)** | HD video requirements, COOP\u002FCOEP headers |\n| **[concepts\u002Fbrowser-support.md](concepts\u002Fbrowser-support.md)** | Feature matrix by browser |\n\n## Examples\n\n| Document | Description |\n|----------|-------------|\n| [examples\u002Fclient-view-basic.md](examples\u002Fclient-view-basic.md) | Basic Client View integration |\n| [examples\u002Fcomponent-view-react.md](examples\u002Fcomponent-view-react.md) | React integration with Component View |\n\n## Troubleshooting\n\n| Document | Description |\n|----------|-------------|\n| **[troubleshooting\u002Ferror-codes.md](troubleshooting\u002Ferror-codes.md)** | All SDK error codes (3000-10000 range) |\n| **[troubleshooting\u002Fcommon-issues.md](troubleshooting\u002Fcommon-issues.md)** | Quick diagnostics and fixes |\n\n## By Topic\n\n### Authentication\n- [SKILL.md#authentication-endpoint](SKILL.md#authentication-endpoint-required) - Signature generation\n- [SKILL.md#authorization-requirements-2026-update](SKILL.md#authorization-requirements-2026-update) - OBF tokens\n\n### HD Video & Performance\n- [concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md) - Enable 720p\u002F1080p\n\n### Events & Callbacks\n- [SKILL.md#event-listeners-client-view](SKILL.md#event-listeners-client-view) - Client View events\n- [SKILL.md#event-listeners-component-view](SKILL.md#event-listeners-component-view) - Component View events\n\n### Government (ZFG)\n- [SKILL.md#zoom-for-government-zfg](SKILL.md#zoom-for-government-zfg) - ZFG configuration\n\n### China CDN\n- [SKILL.md#china-cdn](SKILL.md#china-cdn) - China-specific CDN\n\n## Quick Reference\n\n### Client View vs Component View\n\n| Aspect | Client View | Component View |\n|--------|-------------|----------------|\n| **Object** | `ZoomMtg` | `ZoomMtgEmbedded.createClient()` |\n| **API Style** | Callbacks | Promises |\n| **Password param** | `passWord` (capital W) | `password` (lowercase) |\n| **Events** | `inMeetingServiceListener()` | `on()`\u002F`off()` |\n\n### Key Gotchas\n\n1. **Password spelling differs between views!**\n   - Client View: `passWord` (capital W)\n   - Component View: `password` (lowercase)\n\n2. **SharedArrayBuffer required for HD features**\n   - 720p\u002F1080p video\n   - Gallery view (25 videos)\n   - Virtual backgrounds\n\n3. **March 2026 Authorization Change**\n   - Apps joining external meetings need OBF or ZAK tokens\n\n## External Resources\n\n- **Official docs**: https:\u002F\u002Fdevelopers.zoom.us\u002Fdocs\u002Fmeeting-sdk\u002Fweb\u002F\n- **Client View API**: https:\u002F\u002Fmarketplacefront.zoom.us\u002Fsdk\u002Fmeeting\u002Fweb\u002Findex.html\n- **Component View API**: https:\u002F\u002Fmarketplacefront.zoom.us\u002Fsdk\u002Fmeeting\u002Fweb\u002Fcomponents\u002Findex.html\n- **GitHub samples**: https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-web-sample\n\n## Operations\n\n- [RUNBOOK.md](RUNBOOK.md) - 5-minute preflight and debugging checklist.\n","# Zoom Meeting SDK (Web)\n\nEmbed Zoom meeting capabilities into web applications with two integration options: **Client View** (full-page) or **Component View** (embeddable).\n\n## How to Implement a Custom Video User Interface for a Zoom Meeting in a Web App\n\nUse **Meeting SDK Web Component View**.\n\nDo not use Video SDK for this question unless the user is explicitly building a non-meeting session\nproduct.\n\nMinimal architecture:\n\n```text\nBrowser page\n  -> fetch Meeting SDK signature from backend\n  -> ZoomMtgEmbedded.createClient()\n  -> client.init({ zoomAppRoot })\n  -> client.join({ signature, sdkKey, meetingNumber, userName, password })\n  -> apply layout\u002Fstyle\u002Fcustomize options around the embedded meeting container\n```\n\nMinimal implementation:\n\n```ts\nimport ZoomMtgEmbedded from '@zoom\u002Fmeetingsdk\u002Fembedded';\n\nconst client = ZoomMtgEmbedded.createClient();\n\nexport async function startEmbeddedMeeting(meetingNumber: string, userName: string, password: string) {\n  const sigRes = await fetch('\u002Fapi\u002Fsignature', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application\u002Fjson' },\n    body: JSON.stringify({ meetingNumber, role: 0 }),\n  });\n\n  if (!sigRes.ok) throw new Error(`signature_fetch_failed:${sigRes.status}`);\n\n  const { signature, sdkKey } = await sigRes.json();\n\n  await client.init({\n    zoomAppRoot: document.getElementById('meetingSDKElement')!,\n    language: 'en-US',\n    patchJsMedia: true,\n    leaveOnPageUnload: true,\n    customize: {\n      video: { isResizable: true, popper: { disableDraggable: false } },\n    },\n  });\n\n  await client.join({\n    signature,\n    sdkKey,\n    meetingNumber,\n    userName,\n    password,\n  });\n}\n```\n\nCommon failure points:\n- wrong route: Video SDK instead of Meeting SDK Component View\n- missing backend signature endpoint\n- wrong password field (`password` here, not `passWord`)\n- missing OBF\u002FZAK requirements for meetings outside the app account\n- missing SharedArrayBuffer headers when higher-end meeting features are expected\n\n## Hard Routing Rule\n\nIf the user wants a **custom video user interface for a Zoom meeting in a web app**, route to\n**Component View**, not Video SDK.\n\n- **Meeting SDK Component View** = custom UI for a real Zoom meeting\n- **Video SDK Web** = custom UI for a non-meeting video session product\n\nFor the direct custom-meeting-UI path, start with\n[component-view\u002FSKILL.md](component-view\u002FSKILL.md).\n\n## New to Web SDK? Start Here!\n\n**The fastest way to master the SDK:**\n\n1. **Choose Your View** - [Client View vs Component View](#client-view-vs-component-view) - Understand the key architectural differences\n2. **Quick Start** - [Client View](#quick-start-client-view) or [Component View](#quick-start-component-view) - Get a working meeting in minutes\n3. **SharedArrayBuffer** - [concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md) - Required for HD video, gallery view, virtual backgrounds\n4. **Optional preflight diagnostics** - [..\u002F..\u002Fprobe-sdk\u002FSKILL.md](..\u002F..\u002Fprobe-sdk\u002FSKILL.md) - Validate browser\u002Fdevice\u002Fnetwork before join\n\n**Building a Custom Integration?**\n- Component View gives you Promise-based API and embeddable UI\n- Client View gives you the familiar full-page Zoom experience\n- For a custom meeting UI, prefer **Component View** first\n- Cross-product routing example: [..\u002F..\u002Fgeneral\u002Fuse-cases\u002Fcustom-meeting-ui-web.md](..\u002F..\u002Fgeneral\u002Fuse-cases\u002Fcustom-meeting-ui-web.md)\n- [Browser Support](concepts\u002Fbrowser-support.md) - Feature matrix by browser\n- Exact deep-dive path: [component-view\u002FSKILL.md](component-view\u002FSKILL.md)\n\n**Having issues?**\n- Join errors → Check signature generation and password spelling (`passWord` vs `password`)\n- HD video not working → Enable SharedArrayBuffer headers\n- Complete navigation → [SKILL.md](SKILL.md)\n\n## Prerequisites\n\n- Zoom app with Meeting SDK credentials from [Marketplace](https:\u002F\u002Fmarketplace.zoom.us\u002F)\n- SDK Key (Client ID) and Secret\n- Modern browser (Chrome, Firefox, Safari, Edge)\n- Backend auth endpoint for signature generation\n\n> **Need help with authentication?** See the **[zoom-oauth](..\u002F..\u002Foauth\u002FSKILL.md)** skill for JWT\u002Fsignature generation.\n>\n> **Want pre-join diagnostics?** Chain **[probe-sdk](..\u002F..\u002Fprobe-sdk\u002FSKILL.md)** before `init()`\u002F`join()` to gate low-readiness environments.\n\n## Optional Preflight Gate (Probe SDK)\n\nFor unstable first-join environments, run Probe SDK checks before calling `ZoomMtg.init()` or `client.join()`:\n\n1. Run Probe permissions\u002Fdevice\u002Fnetwork diagnostics.\n2. Apply readiness policy (`allow`, `warn`, `block`).\n3. Continue to Meeting SDK join only for `allow`\u002Fapproved `warn`.\n\nSee [..\u002F..\u002Fprobe-sdk\u002FSKILL.md](..\u002F..\u002Fprobe-sdk\u002FSKILL.md) and [..\u002F..\u002Fgeneral\u002Fuse-cases\u002Fprobe-sdk-preflight-readiness-gate.md](..\u002F..\u002Fgeneral\u002Fuse-cases\u002Fprobe-sdk-preflight-readiness-gate.md).\n\n## Client View vs Component View\n\n**CRITICAL DIFFERENCE**: These are two completely different APIs with different patterns!\n\n| Aspect | Client View | Component View |\n|--------|-------------|----------------|\n| **Object** | `ZoomMtg` (global singleton) | `ZoomMtgEmbedded.createClient()` (instance) |\n| **API Style** | Callbacks | Promises |\n| **UI** | Full-page takeover | Embeddable in any container |\n| **Password param** | `passWord` (capital W) | `password` (lowercase) |\n| **Events** | `inMeetingServiceListener()` | `on()`\u002F`off()` |\n| **Import (npm)** | `import { ZoomMtg } from '@zoom\u002Fmeetingsdk'` | `import ZoomMtgEmbedded from '@zoom\u002Fmeetingsdk\u002Fembedded'` |\n| **CDN** | `zoom-meeting-{VERSION}.min.js` | `zoom-meeting-embedded-{VERSION}.min.js` |\n| **Best For** | Quick integration, standard Zoom UI | Custom layouts, React\u002FVue apps |\n\n### When to Use Which\n\n**Use Client View when:**\n- You want the familiar Zoom meeting interface\n- Quick integration is priority over customization\n- Full-page meeting experience is acceptable\n\n**Use Component View when:**\n- You need to embed meetings in a specific area of your page\n- Building React\u002FVue\u002FAngular applications\n- You want Promise-based async\u002Fawait syntax\n- Custom positioning and resizing is required\n\n## Installation\n\n### NPM (Recommended)\n\n```bash\nnpm install @zoom\u002Fmeetingsdk --save\n```\n\n### CDN\n\n```html\n\u003C!-- Dependencies (required for both views) -->\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Freact.min.js\">\u003C\u002Fscript>\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Freact-dom.min.js\">\u003C\u002Fscript>\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Fredux.min.js\">\u003C\u002Fscript>\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Fredux-thunk.min.js\">\u003C\u002Fscript>\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002F{VERSION}\u002Flib\u002Fvendor\u002Flodash.min.js\">\u003C\u002Fscript>\n\n\u003C!-- Client View -->\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002Fzoom-meeting-{VERSION}.min.js\">\u003C\u002Fscript>\n\n\u003C!-- OR Component View -->\n\u003Cscript src=\"https:\u002F\u002Fsource.zoom.us\u002Fzoom-meeting-embedded-{VERSION}.min.js\">\u003C\u002Fscript>\n```\n\nReplace `{VERSION}` with the [latest version](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002F@zoom\u002Fmeetingsdk) (e.g., `3.11.0`).\n\n## Quick Start (Client View)\n\n```javascript\nimport { ZoomMtg } from '@zoom\u002Fmeetingsdk';\n\n\u002F\u002F Step 1: Check browser compatibility\nconsole.log('System requirements:', ZoomMtg.checkSystemRequirements());\n\n\u002F\u002F Step 2: Preload WebAssembly for faster initialization\nZoomMtg.preLoadWasm();\nZoomMtg.prepareWebSDK();\n\n\u002F\u002F Step 3: Load language files (MUST complete before init)\nZoomMtg.i18n.load('en-US');\nZoomMtg.i18n.onLoad(() => {\n  \n  \u002F\u002F Step 4: Initialize SDK\n  ZoomMtg.init({\n    leaveUrl: 'https:\u002F\u002Fyoursite.com\u002Fmeeting-ended',\n    disableCORP: !window.crossOriginIsolated, \u002F\u002F Auto-detect SharedArrayBuffer\n    patchJsMedia: true,           \u002F\u002F Auto-apply media dependency fixes\n    leaveOnPageUnload: true,      \u002F\u002F Clean up when page unloads\n    externalLinkPage: '.\u002Fexternal.html', \u002F\u002F Page for external links\n    success: () => {\n      \n      \u002F\u002F Step 5: Join meeting (note: passWord with capital W!)\n      ZoomMtg.join({\n        signature: signature,       \u002F\u002F From your auth endpoint\n        meetingNumber: '1234567890',\n        userName: 'User Name',\n        passWord: 'meeting-password', \u002F\u002F Capital W!\n        success: (res) => {\n          console.log('Joined meeting:', res);\n          \n          \u002F\u002F Post-join: Get meeting info\n          ZoomMtg.getAttendeeslist({});\n          ZoomMtg.getCurrentUser({\n            success: (res) => console.log('Current user:', res.result.currentUser)\n          });\n        },\n        error: (err) => {\n          console.error('Join error:', err);\n        }\n      });\n    },\n    error: (err) => {\n      console.error('Init error:', err);\n    }\n  });\n});\n```\n\n## Quick Start (Component View)\n\n```javascript\nimport ZoomMtgEmbedded from '@zoom\u002Fmeetingsdk\u002Fembedded';\n\n\u002F\u002F Create client instance (do this ONCE, not on every render!)\nconst client = ZoomMtgEmbedded.createClient();\n\nasync function startMeeting() {\n  try {\n    \u002F\u002F Initialize with container element\n    await client.init({\n      zoomAppRoot: document.getElementById('meetingSDKElement'),\n      language: 'en-US',\n      debug: true,                  \u002F\u002F Enable debug logging\n      patchJsMedia: true,           \u002F\u002F Auto-apply media fixes\n      leaveOnPageUnload: true,      \u002F\u002F Clean up on page unload\n    });\n\n    \u002F\u002F Join meeting (note: password lowercase!)\n    await client.join({\n      signature: signature,          \u002F\u002F From your auth endpoint\n      sdkKey: SDK_KEY,\n      meetingNumber: '1234567890',\n      userName: 'User Name',\n      password: 'meeting-password',  \u002F\u002F Lowercase!\n    });\n    \n    console.log('Joined successfully!');\n  } catch (error) {\n    console.error('Failed to join:', error);\n  }\n}\n```\n\n## Authentication Endpoint (Required)\n\nBoth views require a JWT signature from a backend server. **Never expose your SDK Secret in frontend code!**\n\n```bash\n# Clone Zoom's official auth endpoint\ngit clone https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-auth-endpoint-sample --depth 1\ncd meetingsdk-auth-endpoint-sample\ncp .env.example .env\n# Edit .env with your SDK Key and Secret\nnpm install && npm run start\n```\n\n### Signature Generation\n\nThe signature encodes:\n- `sdkKey` (or `clientId` for newer apps)\n- `meetingNumber`\n- `role` (0 = participant, 1 = host)\n- `iat` (issued at timestamp)\n- `exp` (expiration timestamp)\n- `tokenExp` (token expiration)\n\n> **IMPORTANT (March 2026)**: Apps joining meetings outside their account will require an App Privilege Token (OBF) or ZAK token. See [Authorization Requirements](#authorization-requirements-2026-update).\n\n## Core Workflow\n\n```\n┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐\n│   Get Signature │───►│   init()        │───►│   join()        │\n│   (from backend)│    │   (SDK setup)   │    │   (enter mtg)   │\n└─────────────────┘    └─────────────────┘    └─────────────────┘\n                              │                       │\n                              ▼                       ▼\n                       success\u002Ferror            success\u002Ferror\n                        callback                 callback\n                     (or Promise resolve)    (or Promise resolve)\n```\n\n## Client View API Reference\n\n### ZoomMtg.init() - Key Options\n\n```javascript\nZoomMtg.init({\n  \u002F\u002F Required\n  leaveUrl: string,              \u002F\u002F URL to redirect after leaving\n\n  \u002F\u002F Display Options\n  showMeetingHeader: boolean,    \u002F\u002F Show meeting number\u002Ftopic (default: true)\n  disableInvite: boolean,        \u002F\u002F Hide invite button (default: false)\n  disableRecord: boolean,        \u002F\u002F Hide record button (default: false)\n  disableJoinAudio: boolean,     \u002F\u002F Hide join audio option (default: false)\n  disablePreview: boolean,       \u002F\u002F Skip A\u002FV preview (default: false)\n  \n  \u002F\u002F HD Video (requires SharedArrayBuffer)\n  enableHD: boolean,             \u002F\u002F Enable 720p (default: true for >=2.8.0)\n  enableFullHD: boolean,         \u002F\u002F Enable 1080p for webinars (default: false)\n  \n  \u002F\u002F View Options\n  defaultView: 'gallery' | 'speaker' | 'multiSpeaker',\n  \n  \u002F\u002F Feature Toggles\n  isSupportChat: boolean,        \u002F\u002F Enable chat (default: true)\n  isSupportCC: boolean,          \u002F\u002F Enable closed captions (default: true)\n  isSupportBreakout: boolean,    \u002F\u002F Enable breakout rooms (default: true)\n  isSupportPolling: boolean,     \u002F\u002F Enable polling (default: true)\n  isSupportQA: boolean,          \u002F\u002F Enable Q&A for webinars (default: true)\n  \n  \u002F\u002F Cross-Origin\n  disableCORP: boolean,          \u002F\u002F For dev without COOP\u002FCOEP headers\n  \n  \u002F\u002F Callbacks\n  success: Function,\n  error: Function,\n});\n```\n\n### ZoomMtg.join() - Key Options\n\n```javascript\nZoomMtg.join({\n  \u002F\u002F Required\n  signature: string,             \u002F\u002F JWT signature from backend\n  meetingNumber: string | number,\n  userName: string,\n  \n  \u002F\u002F Authentication\n  passWord: string,              \u002F\u002F Meeting password (capital W!)\n  zak: string,                   \u002F\u002F Host's ZAK token (required to start)\n  tk: string,                    \u002F\u002F Registration token (if required)\n  obfToken: string,              \u002F\u002F App Privilege Token (for 2026 requirement)\n  \n  \u002F\u002F Optional\n  userEmail: string,             \u002F\u002F Required for webinars\n  customerKey: string,           \u002F\u002F Custom identifier (max 36 chars)\n  \n  \u002F\u002F Callbacks\n  success: Function,\n  error: Function,\n});\n```\n\n### Event Listeners (Client View)\n\n```javascript\n\u002F\u002F User events\nZoomMtg.inMeetingServiceListener('onUserJoin', (data) => {\n  console.log('User joined:', data);\n});\n\nZoomMtg.inMeetingServiceListener('onUserLeave', (data) => {\n  console.log('User left:', data);\n  \u002F\u002F data.reasonCode values:\n  \u002F\u002F 0: OTHER\n  \u002F\u002F 1: HOST_ENDED_MEETING\n  \u002F\u002F 2: SELF_LEAVE_FROM_IN_MEETING\n  \u002F\u002F 3: SELF_LEAVE_FROM_WAITING_ROOM\n  \u002F\u002F 4: SELF_LEAVE_FROM_WAITING_FOR_HOST_START\n  \u002F\u002F 5: MEETING_TRANSFER\n  \u002F\u002F 6: KICK_OUT_FROM_MEETING\n  \u002F\u002F 7: KICK_OUT_FROM_WAITING_ROOM\n  \u002F\u002F 8: LEAVE_FROM_DISCLAIMER\n});\n\nZoomMtg.inMeetingServiceListener('onUserUpdate', (data) => {\n  console.log('User updated:', data);\n});\n\n\u002F\u002F Meeting status\nZoomMtg.inMeetingServiceListener('onMeetingStatus', (data) => {\n  \u002F\u002F status: 1=connecting, 2=connected, 3=disconnected, 4=reconnecting\n  console.log('Meeting status:', data.status);\n});\n\n\u002F\u002F Waiting room\nZoomMtg.inMeetingServiceListener('onUserIsInWaitingRoom', (data) => {\n  console.log('User in waiting room:', data);\n});\n\n\u002F\u002F Active speaker detection\nZoomMtg.inMeetingServiceListener('onActiveSpeaker', (data) => {\n  \u002F\u002F [{userId: number, userName: string}]\n  console.log('Active speaker:', data);\n});\n\n\u002F\u002F Network quality monitoring\nZoomMtg.inMeetingServiceListener('onNetworkQualityChange', (data) => {\n  \u002F\u002F {level: 0-5, userId, type: 'uplink'}\n  \u002F\u002F 0-1 = bad, 2 = normal, 3-5 = good\n  if (data.level \u003C= 1) {\n    console.warn('Poor network quality');\n  }\n});\n\n\u002F\u002F Join performance metrics\nZoomMtg.inMeetingServiceListener('onJoinSpeed', (data) => {\n  console.log('Join speed metrics:', data);\n  \u002F\u002F Useful for performance monitoring dashboards\n});\n\n\u002F\u002F Chat\nZoomMtg.inMeetingServiceListener('onReceiveChatMsg', (data) => {\n  console.log('Chat message:', data);\n});\n\n\u002F\u002F Recording\nZoomMtg.inMeetingServiceListener('onRecordingChange', (data) => {\n  console.log('Recording status:', data);\n});\n\n\u002F\u002F Screen sharing\nZoomMtg.inMeetingServiceListener('onShareContentChange', (data) => {\n  console.log('Share content changed:', data);\n});\n\n\u002F\u002F Transcription (requires \"save closed captions\" enabled)\nZoomMtg.inMeetingServiceListener('onReceiveTranscriptionMsg', (data) => {\n  console.log('Transcription:', data);\n});\n\n\u002F\u002F Breakout room status\nZoomMtg.inMeetingServiceListener('onRoomStatusChange', (data) => {\n  \u002F\u002F status: 2=InProgress, 3=Closing, 4=Closed\n  console.log('Breakout room status:', data);\n});\n```\n\n### Common Methods (Client View)\n\n```javascript\n\u002F\u002F Get current user info\nZoomMtg.getCurrentUser({\n  success: (res) => console.log(res.result.currentUser)\n});\n\n\u002F\u002F Get all attendees\nZoomMtg.getAttendeeslist({});\n\n\u002F\u002F Audio\u002FVideo control\nZoomMtg.mute({ userId, mute: true });\nZoomMtg.muteAll({ muteAll: true });\n\n\u002F\u002F Chat\nZoomMtg.sendChat({ message: 'Hello!', userId: 0 }); \u002F\u002F 0 = everyone\n\n\u002F\u002F Leave\u002FEnd\nZoomMtg.leaveMeeting({});\nZoomMtg.endMeeting({});\n\n\u002F\u002F Host controls\nZoomMtg.makeHost({ userId });\nZoomMtg.makeCoHost({ oderId });\nZoomMtg.expel({ userId });  \u002F\u002F Remove participant\nZoomMtg.putOnHold({ oderId, bHold: true });\n\n\u002F\u002F Breakout rooms\nZoomMtg.createBreakoutRoom({ rooms: [...] });\nZoomMtg.openBreakoutRooms({});\nZoomMtg.closeBreakoutRooms({});\n\n\u002F\u002F Virtual background\nZoomMtg.setVirtualBackground({ imageUrl: '...' });\n```\n\n## Component View API Reference\n\n### client.init() - Key Options\n\n```javascript\nawait client.init({\n  \u002F\u002F Required\n  zoomAppRoot: HTMLElement,      \u002F\u002F Container element\n\n  \u002F\u002F Display\n  language: string,              \u002F\u002F e.g., 'en-US'\n  debug: boolean,                \u002F\u002F Enable debug logging (default: false)\n  \n  \u002F\u002F Media\n  patchJsMedia: boolean,         \u002F\u002F Auto-apply media fixes (default: false)\n  leaveOnPageUnload: boolean,    \u002F\u002F Clean up on page unload (default: false)\n  \n  \u002F\u002F Video\n  enableHD: boolean,             \u002F\u002F Enable 720p\n  enableFullHD: boolean,         \u002F\u002F Enable 1080p\n  \n  \u002F\u002F Customization\n  customize: {\n    video: {\n      isResizable: boolean,\n      viewSizes: { default: { width, height } }\n    },\n    meetingInfo: ['topic', 'host', 'mn', 'pwd', 'telPwd', 'invite', 'participant', 'dc', 'enctype'],\n    toolbar: {\n      buttons: [\n        {\n          text: 'Custom Button',\n          className: 'custom-btn',\n          onClick: () => {\n            console.log('Custom button clicked');\n          }\n        }\n      ]\n    }\n  },\n  \n  \u002F\u002F For ZFG\n  webEndpoint: string,\n  assetPath: string,             \u002F\u002F Custom path for AV libraries (self-hosting)\n});\n```\n\n### client.join() - Key Options\n\n```javascript\nawait client.join({\n  \u002F\u002F Required\n  signature: string,\n  sdkKey: string,\n  meetingNumber: string | number,\n  userName: string,\n  \n  \u002F\u002F Authentication  \n  password: string,              \u002F\u002F Lowercase! (different from Client View)\n  zak: string,                   \u002F\u002F Host's ZAK token\n  tk: string,                    \u002F\u002F Registration token\n  \n  \u002F\u002F Optional\n  userEmail: string,\n});\n```\n\n### Event Listeners (Component View)\n\n```javascript\n\u002F\u002F Connection state\nclient.on('connection-change', (payload) => {\n  \u002F\u002F payload.state: 'Connecting', 'Connected', 'Reconnecting', 'Closed'\n  console.log('Connection:', payload.state);\n});\n\n\u002F\u002F User events\nclient.on('user-added', (payload) => {\n  console.log('Users added:', payload);\n});\n\nclient.on('user-removed', (payload) => {\n  console.log('Users removed:', payload);\n});\n\nclient.on('user-updated', (payload) => {\n  console.log('Users updated:', payload);\n});\n\n\u002F\u002F Active speaker\nclient.on('active-speaker', (payload) => {\n  console.log('Active speaker:', payload);\n});\n\n\u002F\u002F Video state\nclient.on('video-active-change', (payload) => {\n  console.log('Video active:', payload);\n});\n\n\u002F\u002F Unsubscribe\nclient.off('connection-change', handler);\n```\n\n### Common Methods (Component View)\n\n```javascript\n\u002F\u002F Get current user\nconst currentUser = client.getCurrentUser();\n\n\u002F\u002F Get all participants\nconst participants = client.getParticipantsList();\n\n\u002F\u002F Audio control\nawait client.mute(true);\nawait client.muteAudio(userId, true);\n\n\u002F\u002F Video control\nawait client.muteVideo(userId, true);\n\n\u002F\u002F Leave\nclient.leaveMeeting();\n\n\u002F\u002F End (host only)\nclient.endMeeting();\n```\n\n## SharedArrayBuffer (CRITICAL for HD)\n\nSharedArrayBuffer enables advanced features:\n- 720p\u002F1080p video\n- Gallery view\n- Virtual backgrounds\n- Background noise suppression\n\n### Enable with HTTP Headers\n\n```\nCross-Origin-Opener-Policy: same-origin\nCross-Origin-Embedder-Policy: require-corp\n```\n\n### Verify in Browser\n\n```javascript\nif (typeof SharedArrayBuffer === 'function') {\n  console.log('SharedArrayBuffer enabled!');\n} else {\n  console.warn('HD features will be limited');\n}\n\n\u002F\u002F Or check cross-origin isolation\nconsole.log('Cross-origin isolated:', window.crossOriginIsolated);\n```\n\n### Platform-Specific Setup\n\nSee [concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md) for:\n- Vercel, Netlify, AWS CloudFront configuration\n- nginx\u002FApache configuration\n- Service worker fallback for GitHub Pages\n\n### Development Setup (Two-Server Pattern)\n\nThe official samples use a **two-server pattern** for development because COOP\u002FCOEP headers can break navigation:\n\n```javascript\n\u002F\u002F Server 1: Main app (port 9999) - NO isolation headers\n\u002F\u002F Serves index.html, navigation works normally\n\n\u002F\u002F Server 2: Meeting page (port 9998) - WITH isolation headers\n\u002F\u002F Serves meeting.html with SharedArrayBuffer support\n\n\u002F\u002F Main server proxies to meeting server\nproxy: [{\n  path: '\u002Fmeeting.html',\n  target: 'http:\u002F\u002FYOUR_MEETING_SERVER_HOST:9998\u002F'\n}]\n```\n\n**Vite config with headers:**\n```typescript\n\u002F\u002F vite.config.ts\nexport default defineConfig({\n  server: {\n    headers: {\n      'Cross-Origin-Embedder-Policy': 'require-corp',\n      'Cross-Origin-Opener-Policy': 'same-origin',\n    }\n  }\n});\n```\n\n## Common Issues & Solutions\n\n| Issue | Solution |\n|-------|----------|\n| **Join fails with signature error** | Verify signature generation, check sdkKey format |\n| **\"passWord\" typo** | Client View uses `passWord` (capital W), Component View uses `password` |\n| **No HD video** | Enable SharedArrayBuffer headers, check browser support |\n| **Callbacks not firing** | Ensure `inMeetingServiceListener` called after init success |\n| **Virtual background not working** | Requires SharedArrayBuffer + Chrome\u002FEdge |\n| **Screen share fails on Safari** | Safari 17+ with macOS 14+ required for client view |\n\n**Complete troubleshooting**: [troubleshooting\u002Fcommon-issues.md](troubleshooting\u002Fcommon-issues.md)\n\n## Browser Support Matrix\n\n| Feature | Chrome | Firefox | Safari | Edge | iOS | Android |\n|---------|--------|---------|--------|------|-----|---------|\n| 720p (receive) | Yes | Yes | Yes | Yes | Yes | Yes |\n| 720p (send) | Yes* | Yes* | Yes* | Yes* | Yes* | Yes* |\n| Virtual background | Yes | Yes | No | Yes | No | No |\n| Screen share (send) | Yes | Yes | Safari 17+ | Yes | No | No |\n| Gallery view | Yes | Yes | Yes** | Yes | Yes | Yes |\n\n*Requires SharedArrayBuffer\n**Safari 17+ with macOS Sonoma\n\nSee [concepts\u002Fbrowser-support.md](concepts\u002Fbrowser-support.md) for complete matrix.\n\n## Authorization Requirements (2026 Update)\n\n> **IMPORTANT**: Beginning **March 2, 2026**, apps joining meetings outside their account must be authorized.\n\n### Options\n\n1. **App Privilege Token (OBF)** - Recommended for bots\n   ```javascript\n   ZoomMtg.join({\n     ...\n     obfToken: 'your-app-privilege-token'\n   });\n   ```\n\n2. **ZAK Token** - For host operations\n   ```javascript\n   ZoomMtg.join({\n     ...\n     zak: 'host-zak-token'\n   });\n   ```\n\n## Zoom for Government (ZFG)\n\n### Option 1: ZFG-specific NPM Package\n\n```json\n{\n  \"dependencies\": {\n    \"@zoom\u002Fmeetingsdk\": \"3.11.2-zfg\"\n  }\n}\n```\n\n### Option 2: Configure ZFG Endpoints\n\n**Client View:**\n```javascript\nZoomMtg.setZoomJSLib('https:\u002F\u002Fsource.zoomgov.com\u002F{VERSION}\u002Flib', '\u002Fav');\nZoomMtg.init({\n  webEndpoint: 'www.zoomgov.com',\n  ...\n});\n```\n\n**Component View:**\n```javascript\nawait client.init({\n  webEndpoint: 'www.zoomgov.com',\n  assetPath: 'https:\u002F\u002Fsource.zoomgov.com\u002F{VERSION}\u002Flib\u002Fav',\n  ...\n});\n```\n\n## China CDN\n\n```javascript\n\u002F\u002F Set before preLoadWasm()\nZoomMtg.setZoomJSLib('https:\u002F\u002Fjssdk.zoomus.cn\u002F{VERSION}\u002Flib', '\u002Fav');\n```\n\n## React Integration\n\n### Official Pattern (from zoom\u002Fmeetingsdk-react-sample)\n\nThe official React sample uses **imperative initialization** rather than React hooks:\n\n```tsx\nimport { ZoomMtg } from '@zoom\u002Fmeetingsdk';\n\n\u002F\u002F Preload at module level (outside component)\nZoomMtg.preLoadWasm();\nZoomMtg.prepareWebSDK();\n\nfunction App() {\n  const authEndpoint = import.meta.env.VITE_AUTH_ENDPOINT;\n  const meetingNumber = '';\n  const passWord = '';\n  const role = 0;\n  const userName = 'React User';\n\n  const getSignature = async () => {\n    const response = await fetch(authEndpoint, {\n      method: 'POST',\n      headers: { 'Content-Type': 'application\u002Fjson' },\n      body: JSON.stringify({\n        meetingNumber,\n        role,\n      }),\n    });\n    const data = await response.json();\n    startMeeting(data.signature);\n  };\n\n  const startMeeting = (signature: string) => {\n    document.getElementById('zmmtg-root')!.style.display = 'block';\n\n    ZoomMtg.init({\n      leaveUrl: window.location.origin,\n      patchJsMedia: true,\n      leaveOnPageUnload: true,\n      success: () => {\n        ZoomMtg.join({\n          signature,\n          meetingNumber,\n          userName,\n          passWord,\n          success: (res) => console.log('Joined:', res),\n          error: (err) => console.error('Join error:', err),\n        });\n      },\n      error: (err) => console.error('Init error:', err),\n    });\n  };\n\n  return (\n    \u003Cbutton onClick={getSignature}>Join Meeting\u003C\u002Fbutton>\n  );\n}\n```\n\n### React Gotchas (from official samples)\n\n| Issue | Problem | Solution |\n|-------|---------|----------|\n| **Client Recreation** | `createClient()` in component body runs every render | Use `useRef` to persist client |\n| **No useEffect** | Official sample doesn't use React lifecycle hooks | SDK's `leaveOnPageUnload` handles cleanup |\n| **Direct DOM** | Sample uses `getElementById` | Use `useRef\u003CHTMLDivElement>` in production |\n| **No Error State** | Silent failures | Add `useState` for error handling |\n| **Module-Scope Side Effects** | `preLoadWasm()` at top level | May cause issues with SSR |\n\n### Production-Ready React Pattern\n\n```tsx\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport ZoomMtgEmbedded from '@zoom\u002Fmeetingsdk\u002Fembedded';\n\ntype ZoomClient = ReturnType\u003Ctypeof ZoomMtgEmbedded.createClient>;\n\nfunction ZoomMeeting({ meetingNumber, password, userName }: Props) {\n  const clientRef = useRef\u003CZoomClient | null>(null);\n  const containerRef = useRef\u003CHTMLDivElement>(null);\n  const [isJoining, setIsJoining] = useState(false);\n  const [error, setError] = useState\u003Cstring | null>(null);\n\n  \u002F\u002F Create client once\n  useEffect(() => {\n    if (!clientRef.current) {\n      clientRef.current = ZoomMtgEmbedded.createClient();\n    }\n  }, []);\n\n  const joinMeeting = useCallback(async () => {\n    if (!clientRef.current || !containerRef.current) return;\n    \n    setIsJoining(true);\n    setError(null);\n\n    try {\n      \u002F\u002F Get signature from your backend\n      const response = await fetch('\u002Fapi\u002Fsignature', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application\u002Fjson' },\n        body: JSON.stringify({ meetingNumber, role: 0 }),\n      });\n      const { signature, sdkKey } = await response.json();\n      \n      await clientRef.current.init({\n        zoomAppRoot: containerRef.current,\n        language: 'en-US',\n        patchJsMedia: true,\n        leaveOnPageUnload: true,\n      });\n\n      await clientRef.current.join({\n        signature,\n        sdkKey,\n        meetingNumber,\n        password,\n        userName,\n      });\n    } catch (err) {\n      setError(err instanceof Error ? err.message : 'Failed to join');\n    } finally {\n      setIsJoining(false);\n    }\n  }, [meetingNumber, password, userName]);\n\n  return (\n    \u003Cdiv>\n      \u003Cdiv ref={containerRef} style={{ width: '100%', height: '500px' }} \u002F>\n      \u003Cbutton onClick={joinMeeting} disabled={isJoining}>\n        {isJoining ? 'Joining...' : 'Join Meeting'}\n      \u003C\u002Fbutton>\n      {error && \u003Cdiv className=\"error\">{error}\u003C\u002Fdiv>}\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n### Environment Variables (Vite)\n\n```bash\n# .env.local\nVITE_AUTH_ENDPOINT=http:\u002F\u002FYOUR_AUTH_SERVER_HOST:4000\nVITE_SDK_KEY=your_sdk_key\n```\n\n```tsx\nconst authEndpoint = import.meta.env.VITE_AUTH_ENDPOINT;\nconst sdkKey = import.meta.env.VITE_SDK_KEY;\n```\n\n## Detailed References\n\n### Core Documentation\n- **[SKILL.md](SKILL.md)** - Complete navigation guide\n- **[client-view\u002FSKILL.md](client-view\u002FSKILL.md)** - Full Client View reference\n- **[component-view\u002FSKILL.md](component-view\u002FSKILL.md)** - Full Component View reference\n\n### Concepts\n- **[concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md)** - HD video requirements\n- **[concepts\u002Fbrowser-support.md](concepts\u002Fbrowser-support.md)** - Feature matrix by browser\n\n### Troubleshooting\n- **[troubleshooting\u002Ferror-codes.md](troubleshooting\u002Ferror-codes.md)** - All SDK error codes\n- **[troubleshooting\u002Fcommon-issues.md](troubleshooting\u002Fcommon-issues.md)** - Quick diagnostics\n\n### Examples\n- **[client-view\u002FSKILL.md](client-view\u002FSKILL.md)** - Complete Client View guide\n- **[component-view\u002FSKILL.md](component-view\u002FSKILL.md)** - Component View React integration\n\n## Helper Utilities\n\n### Extract Meeting Number from Invite Link\n\n```javascript\n\u002F\u002F Users can paste full Zoom invite links\ndocument.getElementById('meeting_number').addEventListener('input', (e) => {\n  \u002F\u002F Extract meeting number (9-11 digits)\n  let meetingNumber = e.target.value.replace(\u002F([^0-9])+\u002Fi, '');\n  if (meetingNumber.match(\u002F([0-9]{9,11})\u002F)) {\n    meetingNumber = meetingNumber.match(\u002F([0-9]{9,11})\u002F)[1];\n  }\n  \n  \u002F\u002F Auto-extract password from invite link\n  const pwdMatch = e.target.value.match(\u002Fpwd=([\\d,\\w]+)\u002F);\n  if (pwdMatch) {\n    document.getElementById('password').value = pwdMatch[1];\n  }\n});\n```\n\n### Dynamic Language Switching\n\n```javascript\n\u002F\u002F Change language at runtime\ndocument.getElementById('language').addEventListener('change', (e) => {\n  const lang = e.target.value;\n  ZoomMtg.i18n.load(lang);\n  ZoomMtg.i18n.reload(lang);\n  ZoomMtg.reRender({ lang });\n});\n```\n\n### Check System Requirements\n\n```javascript\n\u002F\u002F Check browser compatibility before initializing\nconst requirements = ZoomMtg.checkSystemRequirements();\nconsole.log('Browser info:', JSON.stringify(requirements));\n\nif (!requirements.browserInfo.isChrome && !requirements.browserInfo.isFirefox) {\n  alert('For best experience, use Chrome or Firefox');\n}\n```\n\n## Sample Repositories\n\n| Repository | Description |\n|------------|-------------|\n| [meetingsdk-web-sample](https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-web-sample) | Official samples (Client View & Component View) |\n| [meetingsdk-react-sample](https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-react-sample) | React integration with TypeScript + Vite |\n| [meetingsdk-web](https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-web) | SDK source with helper.html |\n| [meetingsdk-auth-endpoint-sample](https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-auth-endpoint-sample) | Signature generation backend |\n\n## Official Resources\n\n- **Official docs**: https:\u002F\u002Fdevelopers.zoom.us\u002Fdocs\u002Fmeeting-sdk\u002Fweb\u002F\n- **Client View API Reference**: https:\u002F\u002Fmarketplacefront.zoom.us\u002Fsdk\u002Fmeeting\u002Fweb\u002Findex.html\n- **Component View API Reference**: https:\u002F\u002Fmarketplacefront.zoom.us\u002Fsdk\u002Fmeeting\u002Fweb\u002Fcomponents\u002Findex.html\n- **Developer forum**: https:\u002F\u002Fdevforum.zoom.us\u002F\n\n---\n\n**Documentation Version**: Based on Zoom Web Meeting SDK v3.11+\n\n**Need help?** Start with [SKILL.md](SKILL.md) for complete navigation.\n\n\n## Merged from meeting-sdk\u002Fweb\u002FSKILL.md\n\n# Zoom Meeting SDK (Web) - Documentation Index\n\nQuick navigation guide for all Web SDK documentation.\n\n## Start Here\n\n| Document | Description |\n|----------|-------------|\n| **[SKILL.md](SKILL.md)** | Main entry point - Quick starts for both Client View and Component View |\n\n## By View Type\n\n### Client View (Full-Page)\n| Document | Description |\n|----------|-------------|\n| **[client-view\u002FSKILL.md](client-view\u002FSKILL.md)** | Complete Client View reference |\n\n### Component View (Embeddable)\n| Document | Description |\n|----------|-------------|\n| **[component-view\u002FSKILL.md](component-view\u002FSKILL.md)** | Complete Component View reference |\n\n## Concepts\n\n| Document | Description |\n|----------|-------------|\n| **[concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md)** | HD video requirements, COOP\u002FCOEP headers |\n| **[concepts\u002Fbrowser-support.md](concepts\u002Fbrowser-support.md)** | Feature matrix by browser |\n\n## Examples\n\n| Document | Description |\n|----------|-------------|\n| [examples\u002Fclient-view-basic.md](examples\u002Fclient-view-basic.md) | Basic Client View integration |\n| [examples\u002Fcomponent-view-react.md](examples\u002Fcomponent-view-react.md) | React integration with Component View |\n\n## Troubleshooting\n\n| Document | Description |\n|----------|-------------|\n| **[troubleshooting\u002Ferror-codes.md](troubleshooting\u002Ferror-codes.md)** | All SDK error codes (3000-10000 range) |\n| **[troubleshooting\u002Fcommon-issues.md](troubleshooting\u002Fcommon-issues.md)** | Quick diagnostics and fixes |\n\n## By Topic\n\n### Authentication\n- [SKILL.md#authentication-endpoint](SKILL.md#authentication-endpoint-required) - Signature generation\n- [SKILL.md#authorization-requirements-2026-update](SKILL.md#authorization-requirements-2026-update) - OBF tokens\n\n### HD Video & Performance\n- [concepts\u002Fsharedarraybuffer.md](concepts\u002Fsharedarraybuffer.md) - Enable 720p\u002F1080p\n\n### Events & Callbacks\n- [SKILL.md#event-listeners-client-view](SKILL.md#event-listeners-client-view) - Client View events\n- [SKILL.md#event-listeners-component-view](SKILL.md#event-listeners-component-view) - Component View events\n\n### Government (ZFG)\n- [SKILL.md#zoom-for-government-zfg](SKILL.md#zoom-for-government-zfg) - ZFG configuration\n\n### China CDN\n- [SKILL.md#china-cdn](SKILL.md#china-cdn) - China-specific CDN\n\n## Quick Reference\n\n### Client View vs Component View\n\n| Aspect | Client View | Component View |\n|--------|-------------|----------------|\n| **Object** | `ZoomMtg` | `ZoomMtgEmbedded.createClient()` |\n| **API Style** | Callbacks | Promises |\n| **Password param** | `passWord` (capital W) | `password` (lowercase) |\n| **Events** | `inMeetingServiceListener()` | `on()`\u002F`off()` |\n\n### Key Gotchas\n\n1. **Password spelling differs between views!**\n   - Client View: `passWord` (capital W)\n   - Component View: `password` (lowercase)\n\n2. **SharedArrayBuffer required for HD features**\n   - 720p\u002F1080p video\n   - Gallery view (25 videos)\n   - Virtual backgrounds\n\n3. **March 2026 Authorization Change**\n   - Apps joining external meetings need OBF or ZAK tokens\n\n## External Resources\n\n- **Official docs**: https:\u002F\u002Fdevelopers.zoom.us\u002Fdocs\u002Fmeeting-sdk\u002Fweb\u002F\n- **Client View API**: https:\u002F\u002Fmarketplacefront.zoom.us\u002Fsdk\u002Fmeeting\u002Fweb\u002Findex.html\n- **Component View API**: https:\u002F\u002Fmarketplacefront.zoom.us\u002Fsdk\u002Fmeeting\u002Fweb\u002Fcomponents\u002Findex.html\n- **GitHub samples**: https:\u002F\u002Fgithub.com\u002Fzoom\u002Fmeetingsdk-web-sample\n\n## Operations\n\n- [RUNBOOK.md](RUNBOOK.md) - 5-minute preflight and debugging checklist.\n",{"name":5,"triggers":60,"description":71,"user-invocable":56},[61,62,63,64,65,66,67,68,69,70],"embed meeting web","meeting in react","meeting in nextjs","meeting in vue","meeting in angular","component view","client view","web meeting sdk","javascript meeting","sharedarraybuffer","Zoom Meeting SDK for Web - Embed Zoom meeting capabilities into web applications. Two integration\noptions: Client View (full-page, familiar Zoom UI) and Component View (embeddable, Promise-based API).\nIncludes SharedArrayBuffer setup for HD video, gallery view, and virtual backgrounds.\n","main","e605d8ddbfb688da57dfaaceebd93f12a64ef1d3","partner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb",3944,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins","https:\u002F\u002Fgithub.com\u002Fanthropics","https:\u002F\u002Fanthropic.com","2026-11-14 06:21:52",{"source":8,"skillName":5,"commands":81,"prompt":91,"zipAvailable":92},[82,85,88],{"tool":83,"command":84},"npx","npx skills add anthropics\u002Fknowledge-work-plugins --skill zoom-meeting-sdk-web",{"tool":86,"command":87},"bunx","bunx skills add anthropics\u002Fknowledge-work-plugins --skill zoom-meeting-sdk-web",{"tool":89,"command":90},"pnpm","pnpm dlx skills add anthropics\u002Fknowledge-work-plugins --skill zoom-meeting-sdk-web","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002FSKILL.md",true,[94,100,104,108,112,116,120,124,128,132,136,140,144,148],{"path":95,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":98,"sourceHtmlUrl":99},"concepts\u002Fbrowser-support.md","REFERENCE","参考文档",7792,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Fconcepts\u002Fbrowser-support.md",{"path":101,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":102,"sourceHtmlUrl":103},"concepts\u002Fsharedarraybuffer.md",8436,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Fconcepts\u002Fsharedarraybuffer.md",{"path":105,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":106,"sourceHtmlUrl":107},"examples\u002Fclient-view-basic.md",389,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Fexamples\u002Fclient-view-basic.md",{"path":109,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":110,"sourceHtmlUrl":111},"examples\u002Fcomponent-view-react.md",404,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Fexamples\u002Fcomponent-view-react.md",{"path":113,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":114,"sourceHtmlUrl":115},"references\u002Fcomponent-view-breakout-rooms.md",1298,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Freferences\u002Fcomponent-view-breakout-rooms.md",{"path":117,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":118,"sourceHtmlUrl":119},"references\u002Fcomponent-view-ui-customization.md",2026,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Freferences\u002Fcomponent-view-ui-customization.md",{"path":121,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":122,"sourceHtmlUrl":123},"references\u002Fsharedarraybuffer-gallery-view.md",1119,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Freferences\u002Fsharedarraybuffer-gallery-view.md",{"path":125,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":126,"sourceHtmlUrl":127},"references\u002Fweb-performance-cpu.md",966,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Freferences\u002Fweb-performance-cpu.md",{"path":129,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":130,"sourceHtmlUrl":131},"references\u002Fweb-timeout-browser-restriction.md",1118,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Freferences\u002Fweb-timeout-browser-restriction.md",{"path":133,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":134,"sourceHtmlUrl":135},"references\u002Fweb-tracking-id.md",1130,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Freferences\u002Fweb-tracking-id.md",{"path":137,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":138,"sourceHtmlUrl":139},"references\u002Fweb.md",8070,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Freferences\u002Fweb.md",{"path":141,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":142,"sourceHtmlUrl":143},"RUNBOOK.md",2507,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002FRUNBOOK.md",{"path":145,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":146,"sourceHtmlUrl":147},"troubleshooting\u002Fcommon-issues.md",10173,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Ftroubleshooting\u002Fcommon-issues.md",{"path":149,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":150,"sourceHtmlUrl":151},"troubleshooting\u002Ferror-codes.md",9799,"https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fpartner-built\u002Fzoom-plugin\u002Fskills\u002Fmeeting-sdk\u002Fweb\u002Ftroubleshooting\u002Ferror-codes.md",[153,180,205,227,252,278],{"skillNo":154,"name":155,"nameZh":6,"description":156,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":157,"categories":158,"keywords":159,"publishedAt":55},"01M718Y97HCGW12Q53PSJDY03W","ticket-deflector","Reads a forwarded customer email or ticket, pulls order and refund status from a payments connector (PayPal, Square, or Stripe) or Shopify, account history from the CRM, and open tickets from a support desk (Zoho Desk), drafts a tone-matched reply in the owner's writing voice, and can issue a refund through the payments connector with explicit owner approval. With Shopify connected it also runs a proactive order-triage mode that surfaces orders needing attention — unfulfilled past the promised window, payment problems, pending refunds, stuck shipments — and drafts the next action for each before the customer has to ask. Use when the user says \"draft a response,\" \"answer this customer,\" \"where's my order,\" \"I want a refund,\" \"check my orders,\" or \"anything about to blow up.\"","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fsmall-business\u002Fskills\u002Fticket-deflector\u002FSKILL.md",[],[160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179],"ticket","ticket deflector","mode","up","payments","open","writing","when","workflow","ask","Connector","text","mail","window","next","customer","support","crm","past","read",{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":184,"categories":185,"keywords":186,"publishedAt":55},"01M718Y55HFAN5705ME5VEDZ9K","tax-season-organizer","Prepares tax-season materials for the owner's accountant, not tax advice. US federal tax; a non-US business gets its closed-books packet instead. Two modes: (1) quarterly estimated tax from YTD net income in the ledger (MYOB, NetSuite, QuickBooks, Xero, or Zoho Books); (2) year-end 1099 prep, scanning the ledger, PayPal, and Stripe for contractors paid over USD 600 into a 1099-NEC list with missing W-9 flags.\nAny tax request routes first to \u002Ftax-prep, which confirms the books are closed and reconciled before running this skill. Use this skill directly only when the owner says the period's books are already closed: \"books are closed, now do the 1099s,\" \"run the quarterly estimate off the closed numbers,\" or \"just the contractor W-9 list.\"","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fsmall-business\u002Fskills\u002Ftax-season-organizer\u002FSKILL.md",[],[187,188,189,190,191,192,193,194,195,196,167,197,198,199,200,201,179,202,203,204],"tax season organizer","tax","us federal","which","netsuite","paid","end","usd","only","now","books","xero","scanning","run","request","flags","list","stripe",{"skillNo":206,"name":207,"nameZh":6,"description":208,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":209,"categories":210,"keywords":211,"publishedAt":55},"01M718Y13VVPHDD9NTDBVFJ2AZ","tax-prep","Prepares tax materials as a two-link chain — month-end-prep confirms the books are closed and reconciled first, then tax-season-organizer calculates the quarterly estimated payment or builds the year-end 1099-NEC list and accountant packet from those closed numbers. Requires a ledger (MYOB, NetSuite, QuickBooks, Xero, or Zoho Books); uses Gusto, PayPal, and Stripe when connected, else CSV upload. US federal tax math; a non-US business gets the closed-books packet. Prep material for a CPA, never tax advice, nothing filed. Trigger on \"quarterly taxes,\" \"estimated tax payment,\" \"how much should I set aside,\" \"1099s,\" \"1099-NEC,\" \"W-9s,\" \"year-end tax prep,\" \"get my books ready for my accountant,\" any phrasing that suggests a tax deadline is coming, or a question about net profit or YTD income that sounds like worry about a tax bill. An owner who says the period's books are already closed routes to tax-season-organizer directly.","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fsmall-business\u002Fskills\u002Ftax-prep\u002FSKILL.md",[],[212,188,213,214,189,215,216,191,217,218,219,220,221,41,222,193,223,224,225,226],"tax prep","prep","SET","as","ready","never","zoho books","get","chain","profit","trigger","material","question","paypal","business",{"skillNo":228,"name":229,"nameZh":6,"description":230,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":231,"categories":232,"keywords":234,"publishedAt":55},"01M718XWTWQZ01GYSG9T8RW8TW","speed-to-lead","Makes sure no inbound lead goes unanswered. Watches web forms, the shared inbox, and the CRM for new inquiries, qualifies each one against the owner's criteria, drafts a reply in the owner's voice with real meeting times for the owner to approve and send, routes anything hot to a human right away, and logs the whole thing to the CRM. Never sends on its own. Built to run on a schedule so overnight inquiries are drafted and sorted by morning, and works from forwarded or pasted inquiries when no connector is available. Use this whenever the owner is worried about inbound leads or response time — including phrasings like \"leads are going cold,\" \"did anyone answer that inquiry,\" \"I keep missing form submissions,\" \"nothing falls through the cracks,\" \"handle my inbound,\" \"respond to this lead,\" or \"we lose people because nobody gets back fast enough.\" Reach for it for a single unanswered inquiry as readily as for a standing setup.","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fsmall-business\u002Fskills\u002Fspeed-to-lead\u002FSKILL.md",[233],{"categoryNo":30,"categoryName":31,"taxonomyType":32,"taxonomyTypeDesc":33},[235,236,237,238,239,240,217,241,242,243,244,245,246,247,167,248,249,170,250,251],"speed to lead","lead","speed","shared","back","cold","time","inbox","send","respond","new","web forms","people","schedule","logs","sure","human",{"skillNo":253,"name":254,"nameZh":6,"description":255,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":256,"categories":257,"keywords":261,"publishedAt":55},"01M718XQYMN1KY3TPS33967FK0","social-content-engine","Runs the owner's content operation as a standing thing rather than a one-off: keeps a rolling posting calendar, learns the owner's voice, generates on-brand Canva graphics, writes captions that sound like them, repurposes one asset into every channel format, and stages posts for approval instead of publishing on its own. Pulls product photos and prices from Shopify when connected; with no connectors, drafts the calendar and asset briefs for manual posting. Use this whenever the owner talks about posting, content, or social — including \"I need to post more,\" \"we've gone quiet on Instagram,\" \"what should we post this month,\" \"make the content,\" \"give me a month of posts,\" \"write this in my voice,\" \"repurpose this,\" or \"set up our content calendar.\" Reach for it for a single post as readily as for a full quarter. One handoff: a finished, approved campaign brief goes to canva-creator; this skill owns the standing operation.","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fsmall-business\u002Fskills\u002Fsocial-content-engine\u002FSKILL.md",[258],{"categoryNo":259,"categoryName":260,"taxonomyType":32,"taxonomyTypeDesc":33},"01JBSEEDCAT000000000000036","内容创作者",[262,263,264,265,266,267,214,268,269,270,271,163,272,167,273,274,275,179,276,277],"social","social content engine","engine","content engine","social content","content","brief","posts","Captions","prices","campaign","me","product","calendar","write","drafts",{"skillNo":279,"name":280,"nameZh":6,"description":281,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":282,"categories":283,"keywords":284,"publishedAt":55},"01M718XMPJVH0EVRVP998BVZPC","smb-router","The front door to the Small Business plugin. Listens to what the owner needs right now — vague or specific — and routes them to the best skill or slash command for the moment. Also serves as a guide: explains what's available, suggests what to try next, and adapts recommendations based on stored business context. Trigger whenever the owner asks \"what can you do,\" \"help me with my business,\" \"what should I focus on,\" \"I don't know where to start,\" or any open-ended business request that doesn't clearly match a single skill.","https:\u002F\u002Fgithub.com\u002Fanthropics\u002Fknowledge-work-plugins\u002Fblob\u002Fmain\u002Fsmall-business\u002Fskills\u002Fsmb-router\u002FSKILL.md",[],[285,286,287,215,288,41,222,289,165,290,196,226,291,292,293,294,295,273,296,174],"router","smb","smb router","do","front","single","you","vague","can","with","plugin","focus"]