Vanilla JS UI Kit
@rtcstack/ui-vanilla provides an imperative mountVideoConference() function that works with any framework — or no framework at all.
Installation
bash
pnpm add @rtcstack/ui-vanilla @rtcstack/sdk livekit-clientUsage
ts
import { createCall } from '@rtcstack/sdk'
import { mountVideoConference } from '@rtcstack/ui-vanilla'
import '@rtcstack/ui-vanilla/styles.css'
const call = createCall({ token, url })
await call.connect()
const container = document.getElementById('conference')!
const { unmount } = mountVideoConference(container, {
call,
onLeave: () => {
call.disconnect()
unmount()
},
})Parameters
ts
mountVideoConference(
container: HTMLElement,
options: {
call: Call
onLeave?: () => void
theme?: 'dark' | 'light'
showChat?: boolean
}
): { unmount: () => void }| Option | Type | Description |
|---|---|---|
call | Call | A connected Call instance |
onLeave | () => void | Called when the user clicks Leave |
theme | 'dark' | 'light' | Color theme (default: 'dark') |
showChat | boolean | Show chat panel initially (default: false) |
Teardown
Always call unmount() when removing the conference from the DOM. This removes all event listeners attached to the Call instance.
ts
const { unmount } = mountVideoConference(container, { call })
// Later — on route change, modal close, etc.
unmount()Full HTML Example
html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/node_modules/@rtcstack/ui-vanilla/dist/styles.css" />
</head>
<body>
<div id="join-form">
<input id="room" placeholder="Room ID" />
<input id="name" placeholder="Your name" />
<button id="join">Join</button>
</div>
<div id="conference" style="display:none; width:100vw; height:100vh"></div>
<script type="module">
import { createCall } from '@rtcstack/sdk'
import { mountVideoConference } from '@rtcstack/ui-vanilla'
document.getElementById('join').addEventListener('click', async () => {
const roomId = document.getElementById('room').value
const name = document.getElementById('name').value
const { token, url } = await fetch('/api/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ roomId, name, role: 'participant' }),
}).then(r => r.json())
const call = createCall({ token, url })
await call.connect()
document.getElementById('join-form').style.display = 'none'
const container = document.getElementById('conference')
container.style.display = 'block'
const { unmount } = mountVideoConference(container, {
call,
onLeave: () => {
call.disconnect()
unmount()
container.style.display = 'none'
document.getElementById('join-form').style.display = 'block'
},
})
})
</script>
</body>
</html>Theming
The Vanilla kit uses the same CSS custom properties as the React and Vue kits. Override them globally:
css
:root {
--rtc-accent: #6366f1;
--rtc-bg: #0f0f1a;
}See Theming for the full design token reference.

