@vedika-io/embed-loader
v0.2.0
Published
Web component and frame page for embedding the Vedika chat widget in any website. Extends the existing embed.js postMessage protocol with a host adapter that enforces the E4 origin check.
Downloads
108
Maintainers
Readme
@vedika-io/embed-loader
The web component and frame page for embedding the Vedika chat widget in
any website. Extends the existing embed.js validated postMessage
protocol used by WordPress, Shopify and Wix, with a host adapter that
enforces the E4 origin check.
Install
npm install @vedika-io/embed-loader @vedika-io/themeQuick start (10 lines)
The widget never sees your tenant key. Your backend mints a short-lived
session token with POST /api/v1/session/tokens using your server key,
then the browser uses only that token.
// server-side: POST /api/v1/session/tokens with your tenant key in
// `Authorization: Bearer vk_live_...`. Returns { token, expires_at }.
const session = await fetch(`${HARNESS}/api/v1/session/tokens`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.VEDIKA_TENANT_KEY}` },
body: JSON.stringify({ end_user: 'visitor:abc', origin: location.origin }),
}).then(r => r.json());
// browser-side: mount the widget with the session token only.
import('@vedika-io/embed-loader').then(({ mountWidget }) => mountWidget({
organizationId: 'acme', token: session.token,
container: document.getElementById('chat'),
baseUrl: 'https://harness.your-site.com',
}));What you get
| File | What it does |
| ---- | ------------ |
| src/loader.js | The <vedika-chat> web component. |
| src/frame.js | The runtime that lives inside the iframe. |
| src/host-adapter.js | The security boundary on the host page. |
| src/wire.js | The validated postMessage protocol schema. |
| src/theme-tokens.js | XALEN token resolution with accent + dark mode. |
| src/token-mint.js | Browser-side helper that fetches a short-lived token. |
| frame/index.html, frame/embed-frame.js, frame/frame.css | The standalone frame page. |
| samples/{node,python,php} | Server-side mint samples in three languages. |
Quick start
1. Serve the frame page
The frame page must be served from a URL the host page can embed
cross-origin. Drop frame/ behind your CDN at, e.g.,
https://embed.your-site.com/frame/.
2. Mint tokens on your backend
Pick one of the server samples:
// samples/node/mint.mjs
import { mintEmbedToken } from '@vedika-io/embed-loader/samples/node/mint.mjs';
const out = await mintEmbedToken({
serverKey: process.env.VEDIKA_AGENT_KEY,
billingChannel: 'web:example.com',
endUser: 'visitor:abc',
origin: 'https://example.com',
});
res.json({ token: out.token, expiresAt: out.expiresAt });Python and PHP equivalents are in samples/python/mint.py and
samples/php/mint.php.
3. Mount the loader on the host page
<script type="module" src="https://cdn.your-site.com/vedika-embed.js"></script>
<vedika-chat
api-base="https://harness.your-site.com"
token-endpoint="/api/chat/embed-token"
heading="Ask Vedika"
greeting="Namaste — how can I help?"
theme="auto"
accent="#7B5A2B"
position="bottom-right"
></vedika-chat>4. Wire the host adapter (if you build the iframe by hand)
import { createHostAdapter } from '@vedika-io/embed-loader';
const adapter = createHostAdapter({
frame: document.getElementById('vedika-iframe'),
allowedOrigins: ['https://embed.your-site.com'],
});
adapter.on('ready', () => adapter.init({ theme: 'auto', accent: '#7B5A2B' }));
adapter.on('request-token', () => fetch('/api/chat/embed-token', { method: 'POST' })
.then(r => r.json())
.then(t => adapter.setToken(t)));Security
The adapter enforces:
- The message
event.sourceis the iframe the host owns. - The
event.originmatches one of the configuredallowedOrigins. - The payload parses against
wire.js(correct shape and version). - The payload stays under
WIRE_MAX_BYTES(64 KiB).
Anything that fails one of those checks is dropped silently. The
adapter also throttles request-token events to one per 30 s so a
malicious frame cannot exhaust your mint endpoint.
See docs/security.md for the full threat model
and docs/protocol.md for the protocol spec.
Visual testing
The Playwright suite renders the loader at the canonical embed sizes:
- 360 × 640 (small phone)
- 390 × 844 (iPhone 14)
- 768 × 1024 (tablet)
- 1440 × 900 (desktop)
- 360 × 480 embedded (inline)
- 400 × 600 embedded (inline)
cd packages/embed-loader/playwright
npx playwright install --with-deps chromium
npx playwright testLicense
Apache-2.0. See LICENSE.
