Choosing an integration mode
The Recorder widget mounts four different ways. This page is the decision, not the four pages you would otherwise have to read to make it: what you already have decides which mount fits.
Your situation → the mount
Start from what you already have — a React app, a build step, or neither — and read across.
| Your situation | Mount | You gain | You accept |
|---|---|---|---|
| You already have React and a build step | React component | SSR-compatible import — the module never touches window, document, navigator or storage | You own the component tree and its props |
| You have a build step but no React, or you want Shadow DOM isolation | Custom Element | A tag any framework can register, isolated by Shadow DOM | config, editKey and replyToken are JavaScript properties only — setting them as HTML attributes does nothing |
| You have no build step | Script tag | A classic loader mounted on an existing container, configured with data- attributes | No import step, no bundler-driven configuration |
| You do not want to integrate anything, or your page cannot host media capture | Fullpage iframe | The whole recording flow runs on Livstick’s page, isolated from yours | The iframe needs an explicit camera and microphone grant, or recording fails silently |
- Recorder: React component
- SSR-compatible import for an app that already has React and a build step.
- Recorder: Custom Element
- A tag any framework can register, isolated by Shadow DOM.
- Recorder: script tag
- A classic loader for a page with no build step at all.
- Recorder: fullpage iframe
- The whole recording flow runs on Livstick’s page, isolated from yours.
React component
You already have React and a build step. The component is SSR-compatible — it renders a deterministic shell on the server, and the journey initializes after hydration.
import { LivstickWidget } from "@livstick/widget-react-v2";
import "@livstick/widget-react-v2/style.css";
<LivstickWidget uid="code" domain="example.com" />
Custom Element
You have a build step but no React, or you want the Recorder isolated from your page’s styles. The element registers as livstick-widget-v2, and its markup is isolated by Shadow DOM.
import { defineLivstickWidget } from "@livstick/widget-react-v2/element";
defineLivstickWidget();
const widget = document.querySelector("livstick-widget-v2");
widget.editKey = editKey;
Script tag
No build step at all. The classic loader, widget.v2.latest.js, imports the fingerprinted ESM runtime for you and mounts on an existing container using the historical #livstick-plugin id and data- attributes.
Fullpage iframe
You do not want to integrate anything into your page, or your page cannot host media capture at all. The whole Recorder journey runs on Livstick’s fullpage.html, inside an iframe you embed.
<iframe src="https://widget.example.com/fullpage.html" allow="camera; microphone"></iframe>
The Viewer’s surface is smaller
The Viewer only displays a recorded message — it does not record one. Its integration surface reflects that: a React component, and nothing else. There is no Custom Element, no script-tag mount, and no fullpage iframe for the Viewer.
import { LivstickViewer } from "@livstick/widget-viewer";
<LivstickViewer uid="code" domain="example.com" />
- Viewer: React component
- The Viewer’s own reference page, for its full prop list and behavior.