Knowledge-work-plugins zoom-meeting-sdk-web-client-view
install
source · Clone the upstream repo
git clone https://github.com/anthropics/knowledge-work-plugins
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/anthropics/knowledge-work-plugins "$T" && mkdir -p ~/.claude/skills && cp -r "$T/partner-built/zoom-plugin/skills/meeting-sdk/web/client-view" ~/.claude/skills/anthropics-knowledge-work-plugins-zoom-meeting-sdk-web-client-view && rm -rf "$T"
manifest:
partner-built/zoom-plugin/skills/meeting-sdk/web/client-view/SKILL.mdsource content
Zoom Meeting SDK Web - Client View
Full-page Zoom meeting experience embedded in your web application. Client View provides the familiar Zoom interface with minimal customization needed.
Overview
Client View uses the
ZoomMtg global singleton to render a full-page meeting experience identical to the Zoom Web Client.
| Aspect | Details |
|---|---|
| API Object | (global singleton) |
| API Style | Callback-based |
| UI | Full-page takeover |
| Password param | (capital W) |
| Events | |
| Best For | Quick integration, standard Zoom UI |
Installation
NPM
npm install @zoom/meetingsdk --save
import { ZoomMtg } from '@zoom/meetingsdk';
CDN
<script src="https://source.zoom.us/{VERSION}/lib/vendor/react.min.js"></script> <script src="https://source.zoom.us/{VERSION}/lib/vendor/react-dom.min.js"></script> <script src="https://source.zoom.us/{VERSION}/lib/vendor/redux.min.js"></script> <script src="https://source.zoom.us/{VERSION}/lib/vendor/redux-thunk.min.js"></script> <script src="https://source.zoom.us/{VERSION}/lib/vendor/lodash.min.js"></script> <script src="https://source.zoom.us/zoom-meeting-{VERSION}.min.js"></script>
Complete Initialization Flow
// Step 1: Check browser compatibility console.log('Requirements:', ZoomMtg.checkSystemRequirements()); // Step 2: Set CDN path (optional - for China or custom hosting) // ZoomMtg.setZoomJSLib('https://source.zoom.us/{VERSION}/lib', '/av'); // Step 3: Preload WebAssembly modules ZoomMtg.preLoadWasm(); ZoomMtg.prepareWebSDK(); // Step 4: Load language resources ZoomMtg.i18n.load('en-US'); ZoomMtg.i18n.onLoad(() => { // Step 5: Initialize SDK ZoomMtg.init({ leaveUrl: '/meeting-ended', patchJsMedia: true, disableCORP: !window.crossOriginIsolated, success: () => { console.log('SDK initialized'); // Step 6: Join meeting const joinPayload = { signature: signature, meetingNumber: meetingNumber, userName: userName, passWord: passWord, success: (res) => { console.log('Joined meeting'); // Step 7: Post-join operations ZoomMtg.getAttendeeslist({}); ZoomMtg.getCurrentUser({ success: (res) => console.log('Current user:', res.result.currentUser) }); }, error: (err) => console.error('Join failed:', err) }; // IMPORTANT: only include optional fields when they have real values // Passing undefined for some optional fields can cause runtime join errors if (userEmail) joinPayload.userEmail = userEmail; if (tk) joinPayload.tk = tk; if (zak) joinPayload.zak = zak; ZoomMtg.join(joinPayload); }, error: (err) => console.error('Init failed:', err) }); });
ZoomMtg.init() - All Options
Required
| Parameter | Type | Description |
|---|---|---|
| | URL to redirect after leaving meeting |
UI Customization
| Parameter | Type | Default | Description |
|---|---|---|---|
| | | Show meeting number and topic |
| | | Hide invite button |
| | | Hide call out option |
| | | Hide record button |
| | | Hide join audio option |
| | | Skip audio/video preview |
| | | Keep audio panel open |
| | | Prevent overlays on shared content |
| | | Show video tile header |
| | | Show/hide footer |
| | | Enable drag video tiles |
| | | or |
| | | Enable browser URL sharing |
| | | Hide "Share tab audio" checkbox |
| | | Disable PiP mode |
| | | Remove Zoom logo (deprecated) |
| | | , , |
Feature Toggles
| Parameter | Type | Default | Description |
|---|---|---|---|
| | | Enable audio/video |
| | | Enable in-meeting chat |
| | | Enable webinar Q&A |
| | | Enable closed captions |
| | | Enable polling |
| | | Enable breakout rooms |
| | | Enable nonverbal feedback |
| | | Enable Simulive |
| | | Disable VoIP |
| | | Disable report feature |
Video Quality
| Parameter | Type | Default | Description |
|---|---|---|---|
| | (≥2.8.0) | Enable 720p video |
| | | Enable 1080p for webinar attendees |
Advanced
| Parameter | Type | Default | Description |
|---|---|---|---|
| | | Enable debug logging |
| | | Auto-apply media fixes |
| | | Disable web isolation |
| | | Path to helper.html |
| | - | Page for external links |
| | - | For ZFG environments |
| | | Auto cleanup on page close |
| | | Show error dialog on join failure |
| | | Meeting info to display |
| | | Custom invite URL format |
| | | Login popup size |
Callbacks
| Parameter | Type | Description |
|---|---|---|
| | Called on successful init |
| | Called on init failure |
ZoomMtg.join() - All Options
Required
| Parameter | Type | Description |
|---|---|---|
| | SDK JWT from backend (v5.0+: must include appKey prefix) |
| | Meeting or webinar number |
| | Display name |
| | Meeting password (capital W!) |
Authentication
| Parameter | Type | When Required | Description |
|---|---|---|---|
| | Starting as host | Host's Zoom Access Key |
| | Registration required | Registrant token |
| | Webinars | User email |
| | March 2026+ | App Privilege Token |
Optional
| Parameter | Type | Description |
|---|---|---|
| | Custom ID (max 36 chars) |
| | Local recording permission |
Callbacks
| Parameter | Type | Description |
|---|---|---|
| | Called on successful join |
| | Called on join failure |
Event Listeners
User Events
ZoomMtg.inMeetingServiceListener('onUserJoin', (data) => { console.log('User joined:', data); // { userId, userName, ... } }); ZoomMtg.inMeetingServiceListener('onUserLeave', (data) => { console.log('User left:', data); // Reason codes: // 0: OTHER // 1: HOST_ENDED_MEETING // 2: SELF_LEAVE_FROM_IN_MEETING // 3: SELF_LEAVE_FROM_WAITING_ROOM // 4: SELF_LEAVE_FROM_WAITING_FOR_HOST_START // 5: MEETING_TRANSFER // 6: KICK_OUT_FROM_MEETING // 7: KICK_OUT_FROM_WAITING_ROOM // 8: LEAVE_FROM_DISCLAIMER }); ZoomMtg.inMeetingServiceListener('onUserUpdate', (data) => { console.log('User updated:', data); }); ZoomMtg.inMeetingServiceListener('onUserIsInWaitingRoom', (data) => { console.log('User in waiting room:', data); });
Meeting Status
ZoomMtg.inMeetingServiceListener('onMeetingStatus', (data) => { // status: 1=connecting, 2=connected, 3=disconnected, 4=reconnecting console.log('Status:', data.status); });
Audio/Video Events
ZoomMtg.inMeetingServiceListener('onActiveSpeaker', (data) => { // [{userId, userName}] console.log('Active speaker:', data); }); ZoomMtg.inMeetingServiceListener('onNetworkQualityChange', (data) => { // {level: 0-5, userId, type: 'uplink'} // 0-1=bad, 2=normal, 3-5=good console.log('Network quality:', data); }); ZoomMtg.inMeetingServiceListener('onAudioQos', (data) => { console.log('Audio QoS:', data); }); ZoomMtg.inMeetingServiceListener('onVideoQos', (data) => { console.log('Video QoS:', data); });
Chat & Communication
ZoomMtg.inMeetingServiceListener('onReceiveChatMsg', (data) => { console.log('Chat message:', data); }); ZoomMtg.inMeetingServiceListener('onReceiveTranscriptionMsg', (data) => { console.log('Transcription:', data); }); ZoomMtg.inMeetingServiceListener('onReceiveTranslateMsg', (data) => { console.log('Translation:', data); });
Recording & Sharing
ZoomMtg.inMeetingServiceListener('onRecordingChange', (data) => { console.log('Recording status:', data); }); ZoomMtg.inMeetingServiceListener('onShareContentChange', (data) => { console.log('Share content:', data); }); ZoomMtg.inMeetingServiceListener('receiveSharingChannelReady', (data) => { console.log('Sharing channel ready:', data); });
Breakout Rooms
ZoomMtg.inMeetingServiceListener('onRoomStatusChange', (data) => { // status: 2=InProgress, 3=Closing, 4=Closed console.log('Breakout room status:', data); });
Other Events
ZoomMtg.inMeetingServiceListener('onJoinSpeed', (data) => { console.log('Join metrics:', data); }); ZoomMtg.inMeetingServiceListener('onVbStatusChange', (data) => { console.log('Virtual background status:', data); }); ZoomMtg.inMeetingServiceListener('onFocusModeStatusChange', (data) => { console.log('Focus mode:', data); }); ZoomMtg.inMeetingServiceListener('onPictureInPicture', (data) => { console.log('PiP status:', data); }); ZoomMtg.inMeetingServiceListener('onClaimStatus', (data) => { console.log('Host claim status:', data); });
Common Methods
Meeting Info
// Get current user ZoomMtg.getCurrentUser({ success: (res) => console.log(res.result.currentUser) }); // Get all attendees ZoomMtg.getAttendeeslist({}); // Get meeting info ZoomMtg.getCurrentMeetingInfo({ success: (res) => console.log(res) }); // Get SDK version ZoomMtg.getWebSDKVersion({ success: (version) => console.log(version) });
Audio/Video Control
// Mute/unmute specific user ZoomMtg.mute({ userId, mute: true }); // Mute/unmute all ZoomMtg.muteAll({ muteAll: true }); // Stop incoming audio ZoomMtg.stopIncomingAudio({ stop: true }); // Mirror video ZoomMtg.mirrorVideo({ mirror: true });
Chat
// Send chat message ZoomMtg.sendChat({ message: 'Hello!', userId: 0 // 0 = everyone });
Meeting Control
// Leave meeting ZoomMtg.leaveMeeting({}); // End meeting (host only) ZoomMtg.endMeeting({}); // Lock meeting ZoomMtg.lockMeeting({ lock: true });
Host Controls
// Make host ZoomMtg.makeHost({ userId }); // Make co-host ZoomMtg.makeCoHost({ userId }); // Remove co-host ZoomMtg.withdrawCoHost({ userId }); // Remove participant ZoomMtg.expel({ userId }); // Put on hold ZoomMtg.putOnHold({ userId, bHold: true }); // Claim host with host key ZoomMtg.claimHostWithHostKey({ hostKey: '123456' }); // Reclaim host ZoomMtg.reclaimHost({}); // Admit all from waiting room ZoomMtg.admitAll({});
Raise Hand
// Raise hand ZoomMtg.raiseHand({ userId }); // Lower hand ZoomMtg.lowerHand({ oderId }); // Lower all hands ZoomMtg.lowerAllHands({});
Spotlight & Pin
// Spotlight video ZoomMtg.operateSpotlight({ oderId, action: 'add' }); // or 'remove' // Pin video ZoomMtg.operatePin({ oderId, action: 'add' }); // or 'remove' // Allow multi-pin ZoomMtg.allowMultiPin({ allow: true });
Screen Share
// Start screen share ZoomMtg.startScreenShare({}); // Share specific source (Electron) ZoomMtg.shareSource({ source });
Recording
// Start/stop recording ZoomMtg.record({ record: true }); // or false // Show/hide record button ZoomMtg.showRecordFunction({ show: true });
Breakout Rooms
// Create breakout room ZoomMtg.createBreakoutRoom({ rooms: [{ name: 'Room 1' }, { name: 'Room 2' }] }); // Open breakout rooms ZoomMtg.openBreakoutRooms({}); // Close breakout rooms ZoomMtg.closeBreakoutRooms({}); // Join breakout room ZoomMtg.joinBreakoutRoom({ roomId }); // Leave breakout room ZoomMtg.leaveBreakoutRoom({}); // Move user to breakout room ZoomMtg.moveUserToBreakoutRoom({ oderId, roomId }); // Get breakout room status ZoomMtg.getBreakoutRoomStatus({ success: (res) => console.log(res) });
Virtual Background
// Check support ZoomMtg.isSupportVirtualBackground({ success: (data) => console.log(data.result.isSupport) }); // Set virtual background ZoomMtg.setVirtualBackground({ imageUrl: '...' }); // Get VB status ZoomMtg.getVirtualBackgroundStatus({ success: (data) => console.log(data) }); // Lock virtual background (host) ZoomMtg.lockVirtualBackground({ lock: true });
UI Control
// Show/hide meeting header ZoomMtg.showMeetingHeader({ show: true }); // Show/hide invite button ZoomMtg.showInviteFunction({ show: true }); // Show/hide join audio button ZoomMtg.showJoinAudioFunction({ show: true }); // Show/hide callout button ZoomMtg.showCalloutFunction({ show: true }); // Re-render with new options ZoomMtg.reRender({ lang: 'de-DE' });
Language
// Load language ZoomMtg.i18n.load('de-DE'); // Reload language ZoomMtg.i18n.reload('de-DE'); // Get current language ZoomMtg.i18n.getCurrentLang(); // Get all translations ZoomMtg.i18n.getAll();
Rate Limits
| Method | Limit |
|---|---|
| 10 seconds |
| 10 seconds |
| 1 second |
| 5 seconds |
DOM Elements
The SDK automatically adds these elements:
- Main meeting container#zmmtg-root
- Accessibility announcements#aria-notify-area
Do NOT manually create or remove these.
SPA (React/Next) Overlay Gotcha
If you "join" but see a blank/black area or your app shell instead of the meeting UI, the Zoom UI can be rendering behind your app layout. Ensure
#zmmtg-root occupies the viewport and is above other fixed elements:
#zmmtg-root { position: fixed !important; inset: 0 !important; z-index: 9999 !important; }
Join Payload Sanitization Gotcha
If
ZoomMtg.join() succeeds partially but the screen turns black and console shows errors like Cannot read properties of undefined (reading 'toString'), sanitize optional fields before calling join.
Do not pass optional keys with
undefined values (userEmail, tk, zak, etc.). Build a payload and only attach those keys when they are non-empty strings.
Also prefer
defaultView: 'speaker' during ZoomMtg.init() unless you have SharedArrayBuffer/gallery-view prerequisites fully configured.
Resources
- Main Web SDK Skill
- Reference Index
- Error Codes
- Common Issues
- SharedArrayBuffer Setup
- Official API Reference
Operations
- RUNBOOK.md - 5-minute preflight and debugging checklist.