Zoom Meeting SDK Web Component View
AnthropicOfficialCreated by ZoomDistributed by Anthropic
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Zoom Meeting SDK Web Component View allows developers to embed Zoom meeting functionality directly into custom web application layouts. Unlike the full-page Client View, this approach provides a container-based UI that can be integrated into React, Vue, or Angular applications. It utilizes a modern, Promise-based API (async/await) for initialization and meeting management, offering developers granular control over the meeting experience, including custom toolbar buttons, video layout adjustments, and event-driven interactions.
What it does
- Embeds a fully functional Zoom meeting UI into a specific HTML container element.
- Provides a Promise-based API for initializing the client and joining meetings.
- Supports extensive UI customization, including custom toolbar buttons and video layout sizing.
- Enables event-driven programming for audio, video, chat, and participant management.
- Allows for dynamic resizing of the meeting container within the host application.
- Supports advanced features like virtual backgrounds, breakout rooms, and cloud recording.
When to use it
- When you need to build a custom UI wrapper around a Zoom meeting.
- When integrating Zoom into a single-page application (React, Vue, Angular).
- When you require a modern async/await API for managing meeting state.
- When you need to control the specific placement and size of the meeting window on your page.
Advantages
- Seamless integration into existing web layouts via container elements.
- Modern development experience with Promise-based methods.
- High degree of UI customization for a branded user experience.
- Robust event system for monitoring meeting activity and participant status.
Usage examples
- “How do I initialize the Zoom Meeting SDK Component View in a React component?”
- The skill provides a pattern using a useRef hook to hold the client instance and a useEffect hook to initialize the SDK within a specific div container, ensuring the client is created only once.
- “Can I add custom buttons to the Zoom meeting toolbar?”
- Yes, by passing a customize object to the client.init() method, you can define a toolbar array with custom text, CSS classes, and onClick handlers.
- “How do I handle meeting events like users joining or leaving?”
- You can subscribe to events using the client.on() method, specifically listening for 'user-added' and 'user-removed' events to update your application state accordingly.
- “How do I resize the meeting window dynamically?”
- Since the meeting UI is bound to a container element, you can simply update the CSS width and height of that container element to trigger a resize of the embedded Zoom view.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/anthropics/zoom-meeting-sdk-web-component-view/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip zoom-meeting-sdk-web-component-view.zip -d .agents/skills
Documentation by Zoom
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 | ZoomMtgEmbedded.createClient() (instance) |
| API Style | Promise-based (async/await) |
| UI | Embeddable in any container |
| Password param | password (lowercase) |
| Events | on()/off() |
| Best For | Custom layouts, React/Vue/Angular apps |
Installation
NPM
npm install @zoom/meetingsdk --saveimport 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 |
|---|---|---|
zoomAppRoot | HTMLElement | Container element for meeting UI |
Display
| Parameter | Type | Default | Description |
|---|---|---|---|
language | string | 'en-US' | UI language |
debug | boolean | false | Enable debug logging |
Media
| Parameter | Type | Default | Description |
|---|---|---|---|
patchJsMedia | boolean | false | Auto-apply media fixes |
leaveOnPageUnload | boolean | false | Cleanup on page unload |
enableHD | boolean | true | Enable 720p video |
enableFullHD | boolean | false | Enable 1080p video |
Customization
| Parameter | Type | Description |
|---|---|---|
customize | object | UI customization options |
webEndpoint | string | For ZFG: 'www.zoomgov.com' |
assetPath | string | 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 |
|---|---|---|
signature | string | SDK JWT from backend |
sdkKey | string | SDK Key / Client ID |
meetingNumber | string | number | Meeting number |
userName | string | Display name |
Authentication
| Parameter | Type | When Required | Description |
|---|---|---|---|
password | string | If set | Meeting password (lowercase!) |
zak | string | Starting as host | Host's ZAK token |
tk | string | Registration | Registrant token |
userEmail | string | 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 | password | passWord |
| Container | Custom element | Auto #zmmtg-root |
| UI | Embeddable | Full-page |
| Preloading | Not needed | preLoadWasm() |
| Language | Init option | i18n.load() |
| Events | on()/off() | inMeetingServiceListener() |
Resources
Main Web SDK Skill
Error Codes
Common Issues
SharedArrayBuffer Setup
Operations
RUNBOOK.md - 5-minute preflight and debugging checklist.
Files
- ATTRIBUTION.mdAdded by AutoGineer1021 B
- LICENSELicence file added by AutoGineer1.1 KiB
- RUNBOOK.md2.4 KiB
- SKILL.md14.1 KiB
- references/README.md477 B
references/README.md
Component View Reference Index
Use this index when you need the stable entrypoints around Component View behavior before deeper per-method pages are expanded.
SharedArrayBuffer Setup
Error Codes
Common Issues
Requirements and compatibility
Written for: Claude Code, Claude apps
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Claude Code frontmatter, Needs Node.js
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Zoom
- Publisher
- Anthropic (Official)
- Distributed by
- Anthropic
- Source
- anthropics/knowledge-work-plugins · partner-built/zoom-plugin/skills/meeting-sdk/web/component-view · commit e050c2e
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from partner-built/zoom-plugin/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Zoom or Anthropic.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download zoom-meeting-sdk-web-component-view.zip