Skip to content

Web / TypeScript SDK

The Web SDK is the browser-native path — pure TypeScript, no Flutter runtime. Pick the package shape that matches your stack:

  • @twai/core — the engine. Pure TS, no UI. Pair with your own rendering.
  • @twai/player — the player facade. Owns a <video> element + the LiveKit room.
  • @twai/mic — browser mic capture + STT. Opt-in.
  • @twai/react — React hooks + components for the above.
  • @twai/web-component — drop-in <twai-avatar> Custom Element. See Web Component.

Repo: 2waiorg/twai-web-sdk Reference app: samples/nextjs in the toolkit.

Terminal window
# React app
npm install @twai/core @twai/player @twai/react
# Vanilla JS
npm install @twai/core @twai/player
import { useTwaiSession } from '@twai/react';
export function AvatarScreen() {
const { videoRef, send, state } = useTwaiSession({
mintUrl: '/api/mint', // your mint proxy route
avatarId: 'avt_...',
voiceId: 'vc_...',
});
return (
<>
<video ref={videoRef} autoPlay playsInline />
{state === 'ready' && (
<button onClick={() => send('Hi!')}>Say hi</button>
)}
</>
);
}

The hook calls /api/mint (your mint proxy), joins the LiveKit room, subscribes the agent tracks, attaches them to the <video> ref. send(text) publishes a user_text envelope on the lk.chat data-channel topic. state is one of connecting | ready | speaking | rateLimited | failed | disconnected.

import { createEngine } from '@twai/core';
import { createPlayer } from '@twai/player';
const engine = createEngine({
mintUrl: '/api/mint',
avatarId: 'avt_...',
voiceId: 'vc_...',
});
const videoEl = document.getElementById('avatar') as HTMLVideoElement;
const player = createPlayer({ engine, videoElement: videoEl });
await player.connect();
await player.send('Hi!');

Your mint proxy is a trivial route-handler. See the Node tab in Reference integration for the exact code — the SDK calls it via the mintUrl option.

import { createClient } from '@twai/core';
const client = createClient({ mintUrl: '/api/mint' });
const { avatar } = await client.avatars.get('alman', 'dr-alman');
console.log(avatar.displayName, avatar.avatarId);
import { createMic } from '@twai/mic';
const mic = createMic();
await mic.start({ onTranscript: (text) => player.send(text) });

Browser SpeechRecognition on Chrome/Edge/Safari 14.5+. For a server-hosted STT (Whisper etc.), configure transcribeUrl on the mic options.