Web / vanilla JS

For the web SDK, plain HTML pages, Vue, Svelte, or any non-React framework.

1. Drop-in chat widget

Paste this into any HTML page. No build, no framework. The widget hits your backend for a token, opens the chat WebSocket, and renders a minimal but styled chat panel.

<!-- Anywhere in your HTML -->
<div
  id="kl-chat"
  data-channel-id="chn_abc123"
  data-token-url="/api/kardolive/chat-token"
  data-user-id="user_42"
  data-display-name="Yousof"
  style="width: 320px; height: 480px;"
></div>

<script src="https://kardocloud.com/widgets/chat.js" defer></script>

The widget calls POST /api/kardolive/chat-token on your backend (you implement this — see Auth & tokens). The body it sends:

{
  "channelId": "chn_abc123",
  "userId": "user_42",
  "displayName": "Yousof"
}

Your endpoint returns:

{ "token": "<short-lived JWT>", "chatUrl": "wss://chat.kardocloud.com" }

That's it. The widget styles itself for dark backgrounds; override CSS variables on the parent element to theme.

2. @kardolive/sdk

For more control than the drop-in widget but less work than raw WebSocket.

npm install @kardolive/sdk

For your backend (server-to-server):

import { Kardolive } from '@kardolive/sdk';

const kl = new Kardolive({ apiKey: process.env.KARDOLIVE_API_KEY });

// Create a chat channel
const channel = await kl.channels.create({
  type: 'direct',
  memberIds: ['user_42', 'user_99'],
});

// Mint a token for the client
const tok = await kl.channels.mintToken({
  userId: 'user_42',
  channelId: channel.id,
});
// tok = { token, chatUrl, expiresAt }

For your client (browser/mobile) — pass the JWT, NOT the API key:

import { Kardolive } from '@kardolive/sdk';

// JWT comes from your backend (see Auth & tokens)
const kl = new Kardolive({ accessToken: jwtFromYourServer });

// Sessions (calls/conferences) — full mediasoup-client wrapper
const session = await kl.sessions.mintToken('sess_xyz', {
  userId: 'user_42',
  displayName: 'Yousof',
  role: 'guest',
});
// session = { token, sfuUrl, chatUrl, role, perms }

3. Drop-in scenarios

Kardolive ships 7 fully-wired example scenarios as standalone HTML pages. They handle chat + media + interactions out of the box. Pass them ?room=<id>&token=<jwt> and they just work.

ScenarioURLBest for
Live shopping/scenarios/shopping/Product overlay + cart + gifts
Webinar/scenarios/webinar/Q&A queue, big audience
Audio room/scenarios/audio-room/Clubhouse-style
Video call/scenarios/video-call/1:1 telehealth-grade
Voice call/scenarios/voice-call/Audio-only with pulse + dial pad
Karaoke/scenarios/karaoke/Lyrics + tips
Classroom/scenarios/classroom/Whiteboard + hand-raise + breakouts

Open one in an iframe or new window:

// after minting a session token on your backend:
const url = `https://kardocloud.com/scenarios/classroom/?room=${sessionId}&token=${token}`;
window.open(url, '_blank');

// or embed:
<iframe
  src={url}
  width="100%" height="600"
  allow="camera; microphone; display-capture; fullscreen"></iframe>

4. Raw WebSocket — for total control

If you need full UI control and don't want any SDK:

// 1. mint a JWT from your backend (see Auth & tokens)
const { token, chatUrl } = await fetch('/api/kardolive/chat-token', {
  method: 'POST', headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ channelId: 'chn_abc' }),
}).then((r) => r.json());

// 2. open WS
const ws = new WebSocket(
  `${chatUrl}/v1/chat/socket?room=chn_abc&token=${token}`,
);

// 3. send / receive
ws.onopen = () => {
  ws.send(JSON.stringify({ type: 'chat.send', data: { body: 'hello' } }));
};
ws.onmessage = (e) => {
  const env = JSON.parse(e.data);
  switch (env.type) {
    case 'welcome':     console.log('connected as', env.data.you); break;
    case 'chat':        renderMessage(env.data); break;
    case 'chat.edited': updateMessage(env.data); break;
    case 'chat.deleted':removeMessage(env.data.id); break;
    case 'reaction':    addReaction(env.data); break;
    case 'typing':      showTyping(env.data); break;
    case 'presence':    updateViewerCount(env.data); break;
    case 'gift':        floatGift(env.data); break;
    case 'system':      log(env.data.body); break;
  }
};

Sending commands the server understands (full list in reference):

// edit a message you authored
ws.send(JSON.stringify({ type: 'chat.edit', data: { id: 'msg_x', body: 'new body' } }));

// mark read up to now (drives unread counts on other clients)
ws.send(JSON.stringify({ type: 'read.mark', data: {} }));

// typing on/off
ws.send(JSON.stringify({ type: 'typing.start', data: {} }));
ws.send(JSON.stringify({ type: 'typing.stop',  data: {} }));

// emoji reaction on a message
ws.send(JSON.stringify({ type: 'reaction.add', data: { messageId: 'msg_x', emoji: '❤' } }));

// gift / super chat
ws.send(JSON.stringify({ type: 'gift.send',      data: { kind: 'rose', amountCents: 100 } }));
ws.send(JSON.stringify({ type: 'superchat.send', data: { body: 'Great!', amountCents: 500, currency: 'USD' } }));

Next

Chat → · Live stream → · Conference → · Calls →