HOST
No framework
A static page can open the chat. Something on your origin still has to mint the embed token — curl for local, or a tiny POST /sveda/session.
1. Run sveda-server
Token minting is off until
SVEDA_EMBED_ENABLED=true.
Put your page origin in
SVEDA_CORS_ORIGINS
or the browser cannot load the widget CSS/JS.
Full bind and routes:
runtime.
export SVEDA_EMBED_ENABLED=true
export SVEDA_BIND=0.0.0.0:8787
export SVEDA_EMBED_HOST_API_KEY=replace-me
export SVEDA_CORS_ORIGINS=http://127.0.0.1:8000
export DEEPSEEK_API_KEY=sk-...
sveda-server 2. Keep the host key on the server
The browser never sends
SVEDA_EMBED_HOST_API_KEY.
Local-only, you can mint with curl. In anything users will load, add a tiny
POST /sveda/session
on the same origin as the page.
SVEDA_CLIENT_BASE_URL=http://127.0.0.1:8787
SVEDA_CLIENT_HOST_API_KEY=replace-me curl -s http://127.0.0.1:8787/sveda/embed/token \
-H 'content-type: application/json' \
-H 'authorization: Bearer replace-me' \
-d '{"visitor_id":"local-dev"}' 3. Tiny session endpoint (no framework)
Any host that can POST JSON is enough. Return this shape — it is what
sveda-host.js
expects. PHP built-in server, Node
http.createServer,
or a CGI script all work. Handshake:
embed token.
{
"origin": "http://127.0.0.1:8787",
"token": "sveda_embed_…",
"expires_in": 3600,
"appearance": null
} <?php
$origin = rtrim(getenv('SVEDA_CLIENT_BASE_URL') ?: '', '/');
$key = getenv('SVEDA_CLIENT_HOST_API_KEY') ?: '';
$ch = curl_init($origin.'/sveda/embed/token');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'content-type: application/json',
'authorization: Bearer '.$key,
],
CURLOPT_POSTFIELDS => json_encode(['visitor_id' => 'html-host']),
CURLOPT_RETURNTRANSFER => true,
]);
$mint = json_decode(curl_exec($ch), true);
header('content-type: application/json');
echo json_encode([
'origin' => $origin,
'token' => $mint['token'] ?? '',
'expires_in' => $mint['expires_in'] ?? 3600,
'appearance' => $mint['appearance'] ?? null,
]); 4. Iframe (no JS SDK)
After you have a token, point an iframe at
/sveda/embed?token=
on the sidecar. No npm package, no web component.
<iframe
title="Sveda"
src="http://127.0.0.1:8787/sveda/embed?token=sveda_embed_…"
allow="clipboard-write"
style="position:fixed;right:20px;bottom:0;width:400px;height:640px;border:0;background:transparent"
></iframe> 5. In-DOM web component
Load CSS then JS from the sidecar
/build/sveda/
prefix. Do not import the CSS as a JS module.
session
is your mint URL. Call
element.open()
from a host button, or omit
hide-launcher
to use the built-in launcher.
<link rel="stylesheet" href="http://127.0.0.1:8787/build/sveda/sveda-chat.css" />
<script type="module" src="http://127.0.0.1:8787/build/sveda/sveda-chat.js"></script>
<sveda-chat session="/sveda/session" hide-launcher></sveda-chat> 6. Host buttons (JS + iframe)
Serve a copy of
sveda-host.js
from your origin. It reads
data-sveda-origin
and
data-sveda-session,
POSTs for a token, then either mounts
<sveda-chat>
or an iframe. Hide the buttons when the origin env is empty.
<html
lang="en"
data-sveda-origin="http://127.0.0.1:8787"
data-sveda-session="/sveda/session"
>
<body>
<button type="button" data-sveda-open="js">Open JS chat</button>
<button type="button" data-sveda-open="iframe">Open iframe chat</button>
<script type="module" src="/sveda-host.js"></script>
</body>
</html>