@urbantrends/sitechat
v0.1.1
Published
Embeddable, end-to-end encrypted chat widget for websites and apps.
Downloads
26
Maintainers
Readme
@urbantrends/sitechat
Embeddable, end-to-end encrypted chat widget for websites and apps.
Install
npm install @urbantrends/sitechatOr use it with no build step via a CDN (see Option A below). The package ships ESM, CommonJS, and TypeScript types, plus a standalone browser bundle.
Crypto contract
All cryptography in this package uses libsodium-wrappers exclusively, per
the binding Crypto Spec in /CLAUDE.md:
- X25519 keypairs;
crypto_box_seal(sealed boxes) both directions. crypto_pwhash(Argon2id,MODERATE) to derive the wrapping key + auth verifier from the admin code / recovery passphrase.crypto_secretbox(XSalsa20-Poly1305) to wrap the team secret key.
No Web Crypto, no other primitives, no hand-rolled crypto.
Integration
The only configuration a site needs is its public business ID (returned by
POST /api/businesses/) and the API/relay base URL. The admin code never
touches the embedding site — it lives only in the dashboard.
Option A — standalone <script> (no bundler, no React)
Drop in dist/sitechat.js, a single self-contained bundle (its own React +
libsodium inlined). Put config on the tag and it auto-mounts a floating
launcher:
<script
src="https://cdn.jsdelivr.net/npm/@urbantrends/[email protected]/dist/sitechat.js"
data-business-id="biz_abc123"
data-api-url="https://sitechat.urbantrends.dev"
defer
></script>Pin the @<version> in production so a future release can't change the widget
under you. Drop it (.../npm/@urbantrends/sitechat/dist/sitechat.js) to always
track latest.
Mount inline instead of floating by adding a target element — any
[data-sitechat] node gets a widget, config falling back to the script tag:
<div data-sitechat></div>Or mount programmatically against your own container via the window.SiteChat
global:
<div id="support"></div>
<script>
SiteChat.mount(
document.getElementById("support"),
{ businessId: "biz_abc123", apiUrl: "https://sitechat.urbantrends.dev" },
"inline", // or "floating"
);
</script>A runnable demo lives in examples/embed.html.
Option B — React app (bundler)
import { ChatWidget } from "@urbantrends/sitechat";
<ChatWidget businessId="biz_abc123" apiUrl="https://sitechat.urbantrends.dev" />;Option C — headless (own UI, any framework)
import { SiteChatClient } from "@urbantrends/sitechat";
const client = new SiteChatClient({ businessId, apiUrl });
client.on({ message: (m) => render(m.sender, m.text) });
await client.init();
await client.connect();
client.send("Hello"); // sealed to the team key before it leaves the browserScripts
npm run build # bundle with tsup → esm + cjs + d.ts, plus the
# standalone IIFE (dist/sitechat.js, React inlined)
npm run typecheck # tsc --noEmit
npm test # vitest