Skip to content

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-client

Usage

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 }
OptionTypeDescription
callCallA connected Call instance
onLeave() => voidCalled when the user clicks Leave
theme'dark' | 'light'Color theme (default: 'dark')
showChatbooleanShow 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.