Knowledge-work-plugins zoom-meeting-sdk-web-component-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/component-view" ~/.claude/skills/anthropics-knowledge-work-plugins-zoom-meeting-sdk-web-component-view && rm -rf "$T"
manifest:
partner-built/zoom-plugin/skills/meeting-sdk/web/component-view/SKILL.mdsource content
Zoom Meeting SDK Web - Component View
Embeddable Zoom meeting components for flexible integration into any web application. Component View provides Promise-based APIs and customizable UI.
This is the correct web skill for a custom UI around a real Zoom meeting. Do not route to Video SDK unless the user is building a non-meeting custom session product.
Overview
Component View uses
ZoomMtgEmbedded.createClient() to create embeddable meeting components within a specific container element.
| Aspect | Details |
|---|---|
| API Object | (instance) |
| API Style | Promise-based (async/await) |
| UI | Embeddable in any container |
| Password param | (lowercase) |
| Events | / |
| Best For | Custom layouts, React/Vue/Angular apps |
Installation
NPM
npm install @zoom/meetingsdk --save
import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded';
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-embedded-{VERSION}.min.js"></script>
Complete Initialization Flow
import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded'; // Step 1: Create client instance (do once, not on every render!) const client = ZoomMtgEmbedded.createClient(); async function joinMeeting() { try { // Step 2: Get container element const meetingSDKElement = document.getElementById('meetingSDKElement'); // Step 3: Initialize client await client.init({ zoomAppRoot: meetingSDKElement, language: 'en-US', debug: true, patchJsMedia: true, leaveOnPageUnload: true, }); // Step 4: Join meeting await client.join({ signature: signature, sdkKey: sdkKey, meetingNumber: meetingNumber, userName: userName, password: password, // lowercase! userEmail: userEmail, }); console.log('Joined successfully!'); } catch (error) { console.error('Failed to join:', error); } }
client.init() - All Options
Required
| Parameter | Type | Description |
|---|---|---|
| | Container element for meeting UI |
Display
| Parameter | Type | Default | Description |
|---|---|---|---|
| | | UI language |
| | | Enable debug logging |
Media
| Parameter | Type | Default | Description |
|---|---|---|---|
| | | Auto-apply media fixes |
| | | Cleanup on page unload |
| | | Enable 720p video |
| | | Enable 1080p video |
Customization
| Parameter | Type | Description |
|---|---|---|
| | UI customization options |
| | For ZFG: |
| | Custom path for AV libraries |
Customize Object
await client.init({ zoomAppRoot: element, customize: { // Meeting info displayed meetingInfo: [ 'topic', 'host', 'mn', 'pwd', 'telPwd', 'invite', 'participant', 'dc', 'enctype' ], // Video customization video: { isResizable: true, viewSizes: { default: { width: 1000, height: 600 }, ribbon: { width: 300, height: 700 } }, popper: { disableDraggable: false } }, // Custom toolbar buttons toolbar: { buttons: [ { text: 'Custom Button', className: 'custom-btn', onClick: () => { console.log('Custom button clicked'); } } ] }, // Active speaker indicator activeSpaker: { strokeColor: '#00FF00' } } });
client.join() - All Options
Required
| Parameter | Type | Description |
|---|---|---|
| | SDK JWT from backend |
| | SDK Key / Client ID |
| | Meeting number |
| | Display name |
Authentication
| Parameter | Type | When Required | Description |
|---|---|---|---|
| | If set | Meeting password (lowercase!) |
| | Starting as host | Host's ZAK token |
| | Registration | Registrant token |
| | Webinars | User email |
Event Listeners
Syntax
// Subscribe client.on('event-name', callback); // Unsubscribe client.off('event-name', callback);
Connection Events
client.on('connection-change', (payload) => { // payload.state: 'Connecting', 'Connected', 'Reconnecting', 'Closed' console.log('Connection state:', payload.state); if (payload.state === 'Closed') { console.log('Reason:', payload.reason); } });
User Events
client.on('user-added', (payload) => { // Array of users who joined console.log('Users added:', payload); payload.forEach(user => { console.log('User ID:', user.oderId); console.log('Name:', user.displayName); }); }); client.on('user-removed', (payload) => { // Array of users who left console.log('Users removed:', payload); }); client.on('user-updated', (payload) => { // Array of users whose properties changed console.log('Users updated:', payload); });
Audio Events
client.on('active-speaker', (payload) => { // Current active speaker console.log('Active speaker:', payload); }); client.on('audio-statistic-data-change', (payload) => { console.log('Audio stats:', payload); });
Video Events
client.on('video-active-change', (payload) => { // Video state changed console.log('Video active:', payload); }); client.on('video-statistic-data-change', (payload) => { console.log('Video stats:', payload); });
Share Events
client.on('active-share-change', (payload) => { console.log('Share status:', payload); }); client.on('share-statistic-data-change', (payload) => { console.log('Share stats:', payload); });
Chat Events
client.on('chat-on-message', (payload) => { console.log('Chat message:', payload); });
Recording Events
client.on('recording-change', (payload) => { console.log('Recording status:', payload); });
Media Device Events
client.on('media-sdk-change', (payload) => { console.log('Media SDK:', payload); }); client.on('device-change', () => { console.log('Device changed'); });
Common Methods
User Information
// Get current user const currentUser = client.getCurrentUser(); console.log('Current user:', currentUser); // Get all participants const participants = client.getParticipantsList(); console.log('Participants:', participants); // Check if user is host const isHost = client.isHost();
Audio Control
// Mute/unmute self await client.mute(true); // mute await client.mute(false); // unmute // Mute/unmute specific user (host only) await client.muteAudio(userId, true); // Mute all (host only) await client.muteAllAudio(true);
Video Control
// Start/stop video await client.startVideo(); await client.stopVideo(); // Mute/unmute user's video (host only) await client.muteVideo(userId, true);
Meeting Control
// Leave meeting client.leaveMeeting(); // End meeting (host only) client.endMeeting();
Screen Share
// Start screen share await client.startShareScreen(); // Stop screen share await client.stopShareScreen();
Recording
// Start recording (cloud) await client.startCloudRecording(); // Stop recording await client.stopCloudRecording();
Virtual Background
// Check support const isSupported = await client.isSupportVirtualBackground(); // Set virtual background await client.setVirtualBackground(imageUrl); // Remove virtual background await client.removeVirtualBackground();
Rename
// Rename user await client.rename(userId, 'New Name');
React Integration
Basic Pattern
import { useEffect, useRef, useState, useCallback } from 'react'; import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded'; type ZoomClient = ReturnType<typeof ZoomMtgEmbedded.createClient>; function ZoomMeeting({ meetingNumber, password, userName }: Props) { const clientRef = useRef<ZoomClient | null>(null); const containerRef = useRef<HTMLDivElement>(null); const [isJoined, setIsJoined] = useState(false); const [error, setError] = useState<string | null>(null); // Create client once useEffect(() => { if (!clientRef.current) { clientRef.current = ZoomMtgEmbedded.createClient(); } }, []); const joinMeeting = useCallback(async () => { if (!clientRef.current || !containerRef.current) return; try { // Get signature from backend const { signature, sdkKey } = await fetchSignature(meetingNumber); await clientRef.current.init({ zoomAppRoot: containerRef.current, language: 'en-US', patchJsMedia: true, leaveOnPageUnload: true, }); await clientRef.current.join({ signature, sdkKey, meetingNumber, password, userName, }); setIsJoined(true); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to join'); } }, [meetingNumber, password, userName]); return ( <div> <div ref={containerRef} style={{ width: '100%', height: '500px' }} /> {!isJoined && ( <button onClick={joinMeeting}>Join Meeting</button> )} {error && <div className="error">{error}</div>} </div> ); }
Event Handling in React
useEffect(() => { if (!clientRef.current) return; const handleConnectionChange = (payload: any) => { if (payload.state === 'Connected') { setIsJoined(true); } else if (payload.state === 'Closed') { setIsJoined(false); } }; const handleUserAdded = (payload: any) => { console.log('Users joined:', payload); }; clientRef.current.on('connection-change', handleConnectionChange); clientRef.current.on('user-added', handleUserAdded); return () => { clientRef.current?.off('connection-change', handleConnectionChange); clientRef.current?.off('user-added', handleUserAdded); }; }, []);
Positioning and Resizing
Initial Size
await client.init({ zoomAppRoot: element, customize: { video: { viewSizes: { default: { width: 1000, height: 600 } } } } });
Dynamic Resizing
The container element size determines the meeting UI size. To resize:
// Just resize the container document.getElementById('meetingSDKElement').style.width = '1200px'; document.getElementById('meetingSDKElement').style.height = '800px';
Making it Resizable
customize: { video: { isResizable: true } }
Supported Features
Component View supports core meeting functionality. Some features from Client View may not be available.
| Feature | Supported |
|---|---|
| Audio/Video | ✅ |
| Screen Share | ✅ |
| Chat | ✅ |
| Virtual Background | ✅ |
| Breakout Rooms | ✅ |
| Cloud Recording | ✅ |
| Closed Captions | ✅ |
| Live Transcription | ✅ |
| Waiting Room | ✅ |
| Gallery View | ✅ |
| Reactions | ✅ |
| Raise Hand | ✅ |
Contact Zoom Developer Support to request additional features.
Error Handling
try { await client.join({ // ... options }); } catch (error) { // error.reason contains error code // error.message contains description switch (error.reason) { case 'WRONG_MEETING_PASSWORD': console.error('Incorrect password'); break; case 'MEETING_NOT_START': console.error('Meeting has not started'); break; case 'INVALID_PARAMETERS': console.error('Invalid join parameters'); break; default: console.error('Join failed:', error.message); } }
Comparison with Client View
| Feature | Component View | Client View |
|---|---|---|
| API Style | Promises | Callbacks |
| Password param | | |
| Container | Custom element | Auto |
| UI | Embeddable | Full-page |
| Preloading | Not needed | |
| Language | Init option | |
| Events | / | |
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.