Zoom Plugin
Skill 140 of 200
Reference skill for Zoom Video SDK UI Toolkit. Use after routing to a web video workflow when you want prebuilt React UI instead of building a fully custom Video SDK interface.
6 minutes · 1,319 words · 46 sections
Install
npx skills add anthropics/knowledge-work-plugins --skill ui-toolkit/webnpx skills add anthropics/knowledge-work-plugins/plugin marketplace add anthropics/knowledge-work-pluginsThe first command installs just this skill, by the name in its SKILL.md; the second installs the whole repository.
Background reference for the prebuilt Zoom Video SDK UI Toolkit on web. Prefer choose-zoom-approach first when the user might still need Meeting SDK instead.
Official Documentation: https://developers.zoom.us/docs/video-sdk/web/ui-toolkit/ (opens in a new tab) API Reference: https://marketplacefront.zoom.us/sdk/uitoolkit/web/ (opens in a new tab) NPM Package: https://www.npmjs.com/package/@zoom/videosdk-zoom-ui-toolkit (opens in a new tab) Live Demo: https://sdk.zoom.com/videosdk-uitoolkit (opens in a new tab)
New to UI Toolkit? Follow this path:
Having issues?
The Zoom Video SDK UI Toolkit is a pre-built video UI library that renders complete video conferencing experiences with minimal code. Unlike the raw Video SDK, the UI Toolkit provides:
When to use UI Toolkit:
When to use raw Video SDK instead:
npm install @zoom/videosdk-zoom-ui-toolkit jsrsasign
npm install -D @types/jsrsasignNote: React support depends on the UI Toolkit version. Check the package peer dependencies for your installed version (React 18 is commonly required).
import uitoolkit from "@zoom/videosdk-zoom-ui-toolkit";
import "@zoom/videosdk-ui-toolkit/dist/videosdk-zoom-ui-toolkit.css";
const container = document.getElementById("sessionContainer");
const config = {
videoSDKJWT: "your_jwt_token",
sessionName: "my-session",
userName: "John Doe",
sessionPasscode: "",
features: ["video", "audio", "share", "chat", "users", "settings"],
};
uitoolkit.joinSession(container, config);
uitoolkit.onSessionJoined(() => {
console.log("Session joined");
});
uitoolkit.onSessionClosed(() => {
console.log("Session closed");
});'use client';
import { useEffect, useRef } from 'react';
export default function VideoSession({ jwt, sessionName, userName }) {
const containerRef = useRef<HTMLDivElement>(null);
const uitoolkitRef = useRef<any>(null);
useEffect(() => {
let isMounted = true;
const init = async () => {
const uitoolkitModule = await import('@zoom/videosdk-zoom-ui-toolkit');
const uitoolkit = uitoolkitModule.default;
uitoolkitRef.current = uitoolkit;
// If TypeScript complains about CSS imports, configure your app to allow them
// (for example via a global `declare module \"*.css\";`), or import the CSS from
// a global entrypoint (Next.js layout/_app) instead of inlining here.
await import('@zoom/videosdk-ui-toolkit/dist/videosdk-zoom-ui-toolkit.css');
if (!isMounted || !containerRef.current) return;
const config: any = {
videoSDKJWT: jwt,
sessionName: sessionName,
userName: userName,
sessionPasscode: '',
features: ['video', 'audio', 'share', 'chat', 'users', 'settings'],
};
uitoolkit.joinSession(containerRef.current, config);
uitoolkit.onSessionJoined(() => console.log('Joined'));
uitoolkit.onSessionClosed(() => console.log('Closed'));
};
init();
return () => {
isMounted = false;
if (uitoolkitRef.current && containerRef.current) {
try {
uitoolkitRef.current.closeSession(containerRef.current);
} catch (e) {}
}
};
}, [jwt, sessionName, userName]);
return <div ref={containerRef} style={{ width: '100%', height: '100vh' }} />;
}| Feature | Description |
|---|---|
video | Enable video layout and send/receive video |
audio | Show audio button, send/receive audio |
share | Screen sharing |
chat | In-session messaging |
users | Participant list |
settings | Device selection, virtual background |
preview | Pre-join camera/mic preview |
recording | Cloud recording (paid plan) |
leave | Leave/end session button |
Required: Generate JWT tokens on your server, never expose SDK secret client-side.
import { NextRequest, NextResponse } from 'next/server';
import { KJUR } from 'jsrsasign';
const ZOOM_VIDEO_SDK_KEY = process.env.ZOOM_VIDEO_SDK_KEY;
const ZOOM_VIDEO_SDK_SECRET = process.env.ZOOM_VIDEO_SDK_SECRET;
export async function POST(request: NextRequest) {
const { sessionName, role, userName } = await request.json();
if (!sessionName || role === undefined) {
return NextResponse.json({ error: 'Missing params' }, { status: 400 });
}
const iat = Math.floor(Date.now() / 1000);
const exp = iat + 60 * 60 * 2; // 2 hours
const oHeader = { alg: 'HS256', typ: 'JWT' };
const oPayload = {
app_key: ZOOM_VIDEO_SDK_KEY,
role_type: role, // 0 = participant, 1 = host
tpc: sessionName,
version: 1,
iat,
exp,
user_identity: userName || 'User',
};
const signature = KJUR.jws.JWS.sign(
'HS256',
JSON.stringify(oHeader),
JSON.stringify(oPayload),
ZOOM_VIDEO_SDK_SECRET
);
return NextResponse.json({ signature });
}| Field | Required | Description |
|---|---|---|
app_key | Yes | Your Video SDK Key |
role_type | Yes | 0 = participant, 1 = host |
tpc | Yes | Session/topic name |
version | Yes | Always 1 |
iat | Yes | Issued at (Unix timestamp) |
exp | Yes | Expiration (Unix timestamp) |
user_identity | No | User identifier |
uitoolkit.joinSession(container, config);
uitoolkit.closeSession(container);uitoolkit.onSessionJoined(callback);
uitoolkit.onSessionClosed(callback);
uitoolkit.offSessionJoined(callback);
uitoolkit.offSessionClosed(callback);uitoolkit.showChatComponent(container);
uitoolkit.hideChatComponent(container);
uitoolkit.showUsersComponent(container);
uitoolkit.hideUsersComponent(container);
uitoolkit.showControlsComponent(container);
uitoolkit.hideControlsComponent(container);
uitoolkit.showSettingsComponent(container);
uitoolkit.hideSettingsComponent(container);
uitoolkit.hideAllComponents();<link rel="stylesheet" href="https://source.zoom.us/uitoolkit/2.3.5-1/videosdk-zoom-ui-toolkit.css" />
<script src="https://source.zoom.us/uitoolkit/2.3.5-1/videosdk-zoom-ui-toolkit.min.umd.js"></script>
<div id="sessionContainer"></div>
<script>
const uitoolkit = window.UIToolkit;
uitoolkit.joinSession(document.getElementById('sessionContainer'), {
videoSDKJWT: 'your_jwt',
sessionName: 'my-session',
userName: 'User',
features: ['video', 'audio', 'chat']
});
</script>When deploying Next.js under a subpath:
// next.config.ts
const nextConfig = {
basePath: "/your-app-path",
assetPrefix: "/your-app-path",
};Fetch API routes with full path:
fetch('/your-app-path/api/token', { ... })| Browser | Version |
|---|---|
| Chrome | 78+ |
| Firefox | 76+ |
| Safari | 14.1+ |
| Edge | 79+ |
| Issue | Solution |
|---|---|
peer react@"^18.0.0" error | Use the React version required by the installed UI Toolkit package (check peer deps; React 18 is common) |
| CSS import TypeScript error | Configure TS/CSS handling (prefer a global *.css module declaration); avoid @ts-ignore except in throwaway demos |
| Config type error | Type config as any |
| API returns HTML not JSON | Check basePath in fetch URL |
This section was migrated from SKILL.md.
Complete navigation for all UI Toolkit documentation.
New to the UI Toolkit? Follow this learning path:
Understanding how UI Toolkit works:
Complete API documentation:
Core Methods (see skill.md)
joinSession() - Start a video sessioncloseSession() - End session and remove UIdestroy() - Clean up UI Toolkit instanceleaveSession() - Leave without destroying UIComponent Methods (see skill.md)
showControlsComponent() - Display control barshowChatComponent() - Display chat panelshowUsersComponent() - Display participants listshowSettingsComponent() - Display settings panelhideAllComponents() - Hide all componentsEvent Listeners (see skill.md)
onSessionJoined() - Session joined successfullyonSessionClosed() - Session endedonSessionDestroyed() - UI Toolkit destroyedonViewTypeChange() - View mode changedon() - Subscribe to Video SDK eventsoff() - Unsubscribe from eventsInformation Methods (see skill.md)
getSessionInfo() - Get session detailsgetCurrentUserInfo() - Get current usergetAllUser() - Get all participantsgetClient() - Get underlying Video SDK clientversion() - Get version infoControl Methods (see skill.md)
changeViewType() - Switch view modemirrorVideo() - Mirror self videoisSupportCustomLayout() - Check device supportStatistics Methods (see skill.md)
subscribeAudioStatisticData() - Audio quality statssubscribeVideoStatisticData() - Video quality statssubscribeShareStatisticData() - Share quality statsFeature Configuration (see skill.md)
featuresOptions structureSession Configuration (see skill.md)
videoSDKJWT, sessionName, userNamesessionPasscode, sessionIdleTimeoutMinsSee: troubleshooting/common-issues.md (opens in a new tab)
Official Repositories:
| Framework | Repository | Key Features |
|---|---|---|
| React | videosdk-zoom-ui-toolkit-react-sample (opens in a new tab) | Hooks, TypeScript |
| Vue.js | videosdk-zoom-ui-toolkit-vuejs-sample (opens in a new tab) | Composition API |
| Angular | videosdk-zoom-ui-toolkit-angular-sample (opens in a new tab) | Services, Guards |
| JavaScript | videosdk-zoom-ui-toolkit-javascript-sample (opens in a new tab) | Vanilla JS |
| Auth Endpoint | videosdk-auth-endpoint-sample (opens in a new tab) | Node.js JWT |
import uitoolkit from "@zoom/videosdk-zoom-ui-toolkit";
import "@zoom/videosdk-ui-toolkit/dist/videosdk-zoom-ui-toolkit.css";
const config = {
videoSDKJWT: "YOUR_JWT",
sessionName: "test-session",
userName: "User",
featuresOptions: {
video: { enable: true },
audio: { enable: true }
}
};
uitoolkit.joinSession(document.getElementById("container"), config);
uitoolkit.onSessionJoined(() => console.log("Joined"));
uitoolkit.onSessionClosed(() => uitoolkit.destroy());destroy() on cleanuponSessionClosed cleanupjoinSessionNavigation: ← Back to SKILL.md
.env keys and where to find each value.main, last pushed 23 September 2026.SKILL.md, not by matching a directory convention. 27 distinct layouts observed: bio-research/skills/*/SKILL.md, cowork-plugin-management/skills/*/SKILL.md, customer-support/skills/*/SKILL.md, data/skills/*/SKILL.md, design/skills/*/SKILL.md, engineering/skills/*/SKILL.md, enterprise-search/skills/*/SKILL.md, finance/skills/*/SKILL.md, human-resources/skills/*/SKILL.md, legal/skills/*/SKILL.md, marketing/skills/*/SKILL.md, operations/skills/*/SKILL.md, partner-built/apollo/skills/*/SKILL.md, partner-built/brand-voice/skills/*/SKILL.md, partner-built/common-room/skills/*/SKILL.md, partner-built/slack/skills/*/SKILL.md, partner-built/zoom-plugin/skills/*/SKILL.md, partner-built/zoom-plugin/skills/contact-center/*/SKILL.md, partner-built/zoom-plugin/skills/meeting-sdk/*/SKILL.md, partner-built/zoom-plugin/skills/meeting-sdk/web/*/SKILL.md, partner-built/zoom-plugin/skills/video-sdk/*/SKILL.md, partner-built/zoom-plugin/skills/virtual-agent/*/SKILL.md, partner-built/zoom-plugin/skills/zoom-mcp/*/SKILL.md, pdf-viewer/skills/*/SKILL.md, product-management/skills/*/SKILL.md, productivity/skills/*/SKILL.md, sales/skills/*/SKILL.md.h1 and no skipped levels:.claude-plugin/marketplace.json by Anthropic, declaring 120 plugins. It is read for editorial metadata only — never as the skill index, which is always the repository tree./anthropics/knowledge-work-plugins.md, and each skill at its own .md URL.3 files · 4 KB
Everything this skill ships beside its prose. All of it is set here, as subchapters of skill 140.
Documentation the agent loads on demand, rather than up front.
Everything else published alongside the skill.