View as markdown

<livelayer-widget> web component

The custom HTML element registered by @livelayer/sdk. The same element used in the Script tag path — but here you're importing it as part of your bundle instead of via CDN.

Registration

The element auto-registers when you import the SDK module:

ts
import "@livelayer/sdk";

After this import, <livelayer-widget> is available globally as a custom element. Use it anywhere in your HTML / JSX / template.

Attributes

Same set as the Script-tag path. See the Attributes reference for the full list. Most-common:

html
<livelayer-widget
  agent-id="agt_abc123"
  mode="widget"
  position="bottom-right"
  capabilities="navigate,scroll,click">
</livelayer-widget>

Why use the web component instead of the React package?

If you're in a React app, prefer <AvatarWidget> from @livelayer/react — you get React-native lifecycle, hooks integration, page awareness, controlled session, and form filling. The web component does NOT support form filling.

Use <livelayer-widget> directly when:

  • You're in Vue, Svelte, Solid, Lit, Alpine, or vanilla JS.
  • You're in a non-React framework that doesn't have an SDK wrapper yet.
  • You want shadow-DOM isolation (the widget's styles can't be touched by your app's CSS).
  • You want the smallest possible integration footprint.

Manipulating from JavaScript

The element behaves like any other DOM node. Setting attributes triggers the widget's attributeChangedCallback:

ts
import "@livelayer/sdk";

const widget = document.createElement("livelayer-widget");
widget.setAttribute("agent-id", "agt_abc123");
widget.setAttribute("mode", "widget");
widget.setAttribute("capabilities", "navigate,scroll");
document.body.appendChild(widget);

// Later: change agent
widget.setAttribute("agent-id", "agt_xyz789");

// Listen to lifecycle events
widget.addEventListener("livelayer:opened", () => {
  console.log("Visitor opened the widget");
});

widget.addEventListener("livelayer:conversation:started", (e) => {
  console.log("Conversation:", e.detail);
});

// Remove from page (cleans up session)
widget.remove();

Lifecycle methods exposed on the element:

  • connectedCallback() — fires when the element is added to the DOM
  • attributeChangedCallback(name, oldValue, newValue) — fires on attribute changes
  • disconnectedCallback() — fires when the element is removed; aborts in-flight fetches and destroys the session

Shadow DOM

The widget renders into its own shadow root. CSS from your app cannot leak into it; CSS from inside it cannot leak out. The agent inside cannot read your page's text or fill your forms (this is a deliberate boundary).

If you need page awareness or form filling, use the React package.

Capabilities

capabilities="navigate,scroll,click" restricts what the agent can do on your host page. See Script tag → Capabilities.

The web component cannot do form filling — that's a React-only feature because it requires React-state coherence.

Multiple widgets, one page

You can have multiple <livelayer-widget> elements on the same page; each runs an independent session. They don't share state.

For shared state (one session, multiple surfaces), drop the web component and use LiveKitSession directly.

Dimensions and styling

  • mode="widget" — element is display: contents (takes no layout space). Renders a fixed-position bubble inside the shadow root.
  • mode="embedded" — element fills 100% of its parent's width and height. Wrap it to control dimensions.
  • mode="fullscreen" — element renders fixed at 100vw × 100vh.

Events

The widget dispatches CustomEvents on itself, so you can listen at the element level:

ts
widget.addEventListener("livelayer:loaded", () => { /* ... */ });
widget.addEventListener("livelayer:opened", () => { /* ... */ });
widget.addEventListener("livelayer:conversation:started", (e) => { /* e.detail.id */ });
widget.addEventListener("livelayer:conversation:ended", (e) => { /* e.detail.durationSeconds */ });
widget.addEventListener("livelayer:agent:state", (e) => { /* e.detail.state */ });
widget.addEventListener("livelayer:transcript", (e) => { /* e.detail.entries */ });
widget.addEventListener("livelayer:error", (e) => { /* e.detail.code, e.detail.message */ });

Same event catalog as the script-tag path — see Events.