Import the Meeting SDK for web
Import the Meeting SDK for web into your project via npm or the Meeting SDK CDN.
Import via npm
If you installed the Meeting SDK via npm, import ZoomMtg in the component file where you want to use the Meeting SDK:
import { ZoomMtg } from "@zoom/meetingsdk";
Import via CDN
If you installed the Meeting SDK via the CDN, ZoomMtg should already be available in the window.
Init the Meeting SDK
In your component file, add the following JS functions to load the WebAssembly assets:
// loads WebAssembly assets
ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();
Dependent assets
The parameter in the setZoomJSLib function determines where to find the Meeting SDK WebAssembly assets.
- Set to
https://source.zoom.us/{VERSION_NUMBER}/libto use the Zoom hosted assets. - To self-host these assets, pass in your own URL where you are hosting the assets. Find the assets here. Be sure to update these assets each time you upgrade the SDK. Each version includes updated assets in the SDK package.
Set patchJsMedia to true in client.init to point to the latest branch of the dependent assets, instead of a specific version. This allows you to receive hot fixes within the dependent assets automatically. By default, patchJsMedia is false.
See the SDK reference for the full set of ZoomMtg properties.
Using Angular
When using the SDK with Angular, you must run the SDK outside the Angular zone and set up a zone-flags.ts file to disable unnecessary change detection and avoid performance issues.
In the src directory, create a zone-flags.ts file and add the following code:
// disable patching requestAnimationFrame
(window as any).__Zone_disable_requestAnimationFrame = true;
// disable patching specified eventNames
(window as any).__zone_symbol__UNPATCHED_EVENTS = ['message'];
Then, in your angular.json file in the polyfills array, add "src/zone-flags.ts" before zone.js.
"polyfills": [
"src/zone-flags.ts",
"zone.js"
]
Also add it to your tsconfig.app.json file in the include array:
"include": [
"src/**/*.d.ts",
"src/zone-flags.ts"
]
Finally, in your file where you are calling the init and join functions, run them outside the Angular zone. See the example for details.
Meeting SDK for web client view Angular example
import { Component, NgZone } from '@angular/core';
import { ZoomMtg } from '@zoom/meetingsdk';
ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private ngZone: NgZone) {
}
// ...
join() {
this.ngZone.runOutsideAngular(() => {
ZoomMtg.init({
leaveUrl: leaveUrl, // https://example.com/thanks-for-joining
success: (success) => {
ZoomMtg.join({
signature: signature, // role in SDK signature needs to be 1
meetingNumber: meetingNumber,
passWord: passWord,
userName: userName,
zak: zakToken, // the host's ZAK token
success: (success) => {
console.log(success)
},
error: (error) => {
console.log(error)
}
})
},
error: (error) => {
console.log(error)
}
})
})
}
// ...
}
Appended DOM elements
When imported, the Meeting SDK client view adds new elements to the DOM to handle client overlays and accessibility elements. The following elements are added to the end of <body></body>:
<body>
<!-- added on import -->
</div>
<div id="aria-notify-area">
</body>
When ZoomMtg.init() is called, additional DOM elements are appended to include core in-meeting UI and functions:
index.html
<body class="ReactModal__Body--open">
<!-- added on import -->
</div>
<div id="aria-notify-area">
<!-- added on meeting init -->
</div>
<div class="ReactModalPortal">
</div>
<div class="ReactModalPortal">
</div>
<div class="sharer-controlbar-container sharer-controlbar-container--hidden">
</body>
To show or hide the meeting UI from your app, target #zmmtg-root directly:
const zoomMeetingSDK = document.getElementById("zmmtg-root");
// To hide
zoomMeetingSDK.style.display = "none";
// To show
zoomMeetingSDK.style.display = "block";
Avoid CSS conflicts in host applications
Because the SDK injects the previously shown elements into your host document and loads its own stylesheet (based on Bootstrap and React Select), SDK styles and host styles can collide in either direction.
Conflicts are especially likely when the host uses a CSS reset, a utility-first framework such as Tailwind CSS, or a component library such as Bootstrap or MUI, which redefine base selectors (body, *, headings, button) that the SDK also relies on.
Mitigate this using one of the following options, listed by isolation strength, strongest first.
Option 1 - Dedicated route or subdomain (recommended)
Mount client view on a dedicated route (for example, /meeting) or subdomain (for example, meeting.example.com) that does not load your application's global CSS framework or reset. Because the SDK and your host UI never coexist on the same page, conflicts cannot occur.
Option 2 - iFrame embed
Embed client view in an <iframe> so the SDK stylesheet and the #zmmtg-root container live in a separate document from your host application. See Best practices using the Meeting SDK in an iFrame for setup details, including the required allow attributes for camera, microphone, and screen sharing.
Option 3 - Scope host styles away from the SDK roots
Wrap your host application's global rules in a :not() selector that excludes the two elements client view appends to <body>:
body > *:not(#zmmtg-root):not(#aria-notify-area) {
/* host application's global styles */
}
This is the lightest option but the most fragile. The body > * combinator only targets direct children of <body>, so deeply nested global rules such as * { box-sizing: border-box } can still bleed into the SDK. Future SDK releases may also add new top-level elements that you would need to add to the :not() chain manually.
Comparison
| Option | Isolation | Effort | Stability |
|---|---|---|---|
| Dedicated route or subdomain | Strongest | Medium, routing and code split | Highest |
| iFrame embed | Strong | Higher, cross-frame messaging | High |
:not() scoping | Weakest | Low, CSS-only change | Low, fragile to SDK updates |