The <conference-room> widget
A distributable web component that wraps a live confcall room in an iframe and re-emits its
lifecycle as DOM CustomEvents — the same custom-element developer experience as
@confcall/agent-widget, but iframe-isolated so it survives CRM sandboxes
(Salesforce Lightning Locker, ServiceNow OpenFrame, Dynamics CIF).
Install
Script tag:
<script src="https://widget.confcall.app/conference-widget.umd.js"></script>
or as an npm package:
npm install @confcall/conference-widget
import '@confcall/conference-widget';
Quick start
<conference-room
room-id="room-abc123"
base-url="https://meet.confcall.app"
display-name="Ada Lovelace"
></conference-room>
Without an auth-token, the embedded page shows a "Sign in for host access" affordance
that opens the AuthService popup flow; a visitor can still join and participate as a guest without
signing in.
In practice, set room-id and auth-token from the response of
POST /api/embed/sessions — see the
two-call smoke sequence on the overview page.
Attributes
| Attribute | Required | Description |
|---|---|---|
room-id | Yes | The confcall room to join. |
base-url | Yes |
Origin of the confcall deployment — origin only
(e.g. https://meet.confcall.app), no path, no trailing slash. The element appends
/embed/room/{room-id} itself; a base-url that already includes a path
produces a broken, doubled URL.
|
auth-token | No |
A JWT (popup-flow token, or a control-plane embed session token from
POST /api/embed/sessions). When set, the embed page skips the popup sign-in and
joins with the token's role immediately.
|
display-name | No | Pre-fills the guest display name. |
layout | No |
mobile (default) or desktop. The embed always renders the mobile
in-call layout regardless — this only affects the query param forwarded to the embed page.
|
Changing any attribute updates the iframe's src in place — no element remount.
base-url must be a bare origin. A prior widget
(agent-widget) once double-appended a URL suffix because a server-side snippet
generator emitted a value that already contained the path it appended again. If you generate this
attribute from server-side config, assert it's a bare origin before interpolating it.
Events
All events bubble and are composed, so they cross the iframe/element boundary and can be listened for anywhere in the host page's DOM.
| Event | detail | Fires when |
|---|---|---|
conference-joined | { roomId, participantCount } | The local participant joins. |
conference-left | { reason: 'leave' | 'kicked' | 'ended' | 'denied' } | The local participant leaves, for any reason. |
conference-participant-joined | { userId, name, isAiAgent } | A remote participant (including the AI agent) joins. |
conference-participant-left | { userId, name, isAiAgent } | A remote participant leaves. |
conference-meeting-ended | { roomId } | The host ends the meeting for everyone. |
conference-auth-required | { action } | A guest attempts a host-only action (e.g. inviting the AI agent) without an auth-token. |
conference-error | { code, message } | A recoverable embed-page error. |
const room = document.querySelector('conference-room');
room.addEventListener('conference-joined', (e) => {
console.log('joined room', e.detail.roomId, 'participants:', e.detail.participantCount);
});
room.addEventListener('conference-meeting-ended', () => {
room.remove();
});
Messages are only accepted from the element's own iframe at the base-url origin —
anything else is silently ignored.
Sizing
The element has no intrinsic size; size its container the same way you would any iframe:
<div style="width: 400px; height: 700px;">
<conference-room room-id="room-abc123" base-url="https://meet.confcall.app"></conference-room>
</div>
Scope exclusions (v1)
- E2EE rooms aren't supported — the embed page shows an "open in full app" notice instead of joining.
- Desktop in-panel layout isn't supported — the embed always renders the mobile layout tree.
- Screen-share initiation requires the host page's iframe
allowpolicy to permitdisplay-capture(set by default; don't strip it via a wrapping CSP). - No pop-out — to open a call in its own window today, link to
{base-url}/room/{roomId}directly instead of the widget.
Full source and build instructions: conference-widget/README.md in the confcall repo.
Design rationale: specs/RFC-Conference-Room-Embed.md (Phase 3).