From zoom-skills
Provides pre-built React-based video conferencing UI via Zoom Video SDK. Drop-in composite UI or individual components for instant video sessions with minimal code.
How this skill is triggered — by the user, by Claude, or both
Slash command
/zoom-skills:ui-toolkitThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Pre-built video conferencing UI powered by Zoom Video SDK. Drop-in solution for web applications.
Pre-built video conferencing UI powered by Zoom Video SDK. Drop-in solution for web applications.
Official Documentation: https://developers.zoom.us/docs/video-sdk/web/ui-toolkit/ API Reference: https://marketplacefront.zoom.us/sdk/uitoolkit/web/ NPM Package: https://www.npmjs.com/package/@zoom/videosdk-zoom-ui-toolkit Live Demo: https://sdk.zoom.com/videosdk-uitoolkit
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/jsrsasign
Note: 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();
example version 2.4.0-1
<link rel="stylesheet" href="https://source.zoom.us/uitoolkit/{VERSION}/videosdk-ui-toolkit.css" />
<script src="https://source.zoom.us/uitoolkit/{VERSION}/videosdk-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
Official Repositories:
| Framework | Repository | Key Features |
|---|---|---|
| React | videosdk-zoom-ui-toolkit-react-sample | Hooks, TypeScript |
| Vue.js | videosdk-zoom-ui-toolkit-vuejs-sample | Composition API |
| Angular | videosdk-zoom-ui-toolkit-angular-sample | Services, Guards |
| JavaScript | videosdk-zoom-ui-toolkit-javascript-sample | Vanilla JS |
| Auth Endpoint | videosdk-auth-endpoint-sample | 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.npx claudepluginhub zoom/skills --plugin zoom-skillsBuilds custom real-time video experiences using Zoom's Video SDK with full UI control. Covers web, React Native, Flutter, Android, iOS, macOS, Unity, and Linux.
Build accessible UIs with gluestack-ui components for React and React Native. Covers CLI installation, composition, variants, sizes, states, accessibility props, and platform specifics.
Guides building production-quality UIs with component architecture, accessibility, and state management. Use when creating or modifying user-facing interfaces.