@deewanio/client
v0.3.1
Published
Deewan for the browser: join an end-to-end encrypted Deewan meeting and build your own interface — media, chat, reactions, hands, polls, captions, webinar Q&A and strict encryption.
Maintainers
Readme
@deewanio/client
Build your own meeting interface in the browser on Deewan. This package connects to an end-to-end encrypted Deewan meeting and gives you plain objects and events for everything a participant can do in Deewan's own interface. People using your interface, Deewan's website, Deewan's apps and the React Native and Flutter SDKs are all in the same meeting.
npm install @deewanio/clientWorks with any bundler that supports new URL(…, import.meta.url) workers (Vite, webpack 5,
Next.js, Parcel, esbuild). Requires a current Chrome, Edge, Firefox or Safari.
Quick start
import { joinMeeting } from "@deewanio/client";
// Your server calls POST /rooms/{id}/tokens (or @deewanio/sdk's rooms.createToken) and returns the response.
const token = await fetch("/api/meeting-token", { method: "POST" }).then((r) => r.json());
const meeting = await joinMeeting(token, { publish: { camera: true, microphone: true } });
meeting.on("participants", (people) => render(people));
meeting.on("trackSubscribed", ({ participantId, kind, attach }) => {
const el = document.createElement(kind === "video" ? "video" : "audio");
el.autoplay = true;
attach(el);
document.querySelector(`#tile-${participantId}`)?.append(el);
});A new trackSubscribed listener also receives every track already playing, so people
who were there before you appear straight away.
Everything a participant can do
| You want to… | Call | Everyone else sees |
|---|---|---|
| Camera, microphone, screen | setCamera(on) · setMicrophone(on) · setScreenShare(on) | trackSubscribed, participants |
| Pick devices | devices(kind) · useDevice(kind, deviceId) | — |
| Chat and reactions | sendMessage(text) · sendReaction(emoji) | message · reaction |
| Raise a hand | raiseHand(true \| false) | handRaised, handRaisedAt |
| Answer a poll | polls() · vote(pollId, optionIds) | pollsChanged |
| Live captions for yourself | setCaptions(true) | caption lines (yours only) |
| Webinar Q&A | ask(text) · voteQuestion(id) · hosts: markQuestion(id, { answered, hidden }) | questions |
| Recording indicator | meeting.recording | recording event |
| Breakout announcements | — | announcement event |
| Strict encryption | exchangeKey() before the token | security event: the code to compare |
| Leave | leave() | participants |
Host powers (muting or removing people, the webinar stage, breakouts, recording) belong to
your server, through the REST API or @deewanio/sdk.
Participants
meeting.participants() returns everyone, you first, as plain objects:
id, name, isSelf, isHost, isCohost, isGuest, micOn, camOn, isScreenSharing,
isSpeaking, handRaised, handRaisedAt, captionsOn, onStage, isAudience.
Events
participants · trackSubscribed · trackUnsubscribed · message · reaction ·
pollsChanged · caption · questions · recording · announcement · security ·
kindChanged · disconnected ("left", "removed", "ended" or "error").
meeting.on(event, listener) returns a function that removes the listener.
Strict end-to-end encryption
In a room with encryption: "strict" the meeting key exists only on participants' devices —
not even Deewan can read the meeting.
import { exchangeKey, joinMeeting } from "@deewanio/client";
const key = await exchangeKey(); // the private half never leaves this page
const token = await fetch("/api/meeting-token", { method: "POST", body: JSON.stringify({ key }) }).then((r) => r.json());
// On your server: deewan.rooms.createToken(roomId, { name, exchange_key: key })
const meeting = await joinMeeting(token);
meeting.on("security", ({ ready, code }) => {
// `code` is identical on every screen, Deewan's own apps included: read it out to check.
});Webinars
In a webinar room, check meeting.kind and each participant's onStage / isAudience
before showing publish controls. Only hosts and people a host invited may publish; the
media server enforces it whatever the interface does.
Errors
Participant actions throw DeewanError with the API's status and code (for example
conflict for a closed poll, or rate_limited).
Security
- Everything a participant sends is encrypted on their device before it leaves.
- Hands, polls, captions and strict-room keys go through Deewan's Participant API, authenticated by the participant's own room token — never by your API key — and only over HTTPS.
- A room token is personal: issue one per person from your server.
Links
- Guide: https://deewan.io/en/docs/sdk#browser
- API reference: https://deewan.io/en/docs/reference
- Support: [email protected]
MIT © Deewan
