@akson/chatsuite-session-embed
v0.2.0
Published
Drop-in WhatsApp session status pill + QR scan modal for ChatSuite consumers, plus a headless SessionMonitor for SSR/Node use.
Readme
@akson/chatsuite-session-embed
Drop-in WhatsApp session status pill + QR scan modal for any web app that consumes ChatSuite.
External apps (the MyArmy Meteor app, future integrations) can render a live status indicator and a self-refreshing QR modal with one script tag and an API token, so end users always see the latest QR while Baileys rotates it every ~20 seconds.
Install
Script tag (recommended)
<script src="https://api.chatsuite.akson.ch/embed/chatsuite-session.js" defer></script>
<chatsuite-session-status
api-base="https://api.chatsuite.akson.ch"
tel="+41764113232"
data-token="wa_..."
auto-open="true"></chatsuite-session-status>The custom element upgrades as soon as the bundle loads. No build step required.
ESM (bundlers)
pnpm add @akson/chatsuite-session-embedimport {
SessionMonitor,
registerSessionStatusElement,
} from '@akson/chatsuite-session-embed';
// Either register the custom element …
registerSessionStatusElement();
// … or drive your own UI from the headless monitor:
const monitor = new SessionMonitor({
apiBase: 'https://api.chatsuite.akson.ch',
tel: '+41764113232',
token: process.env.CHATSUITE_TOKEN!,
});
monitor.on('qr', (snap) => render(snap.qr));
monitor.on('state', (snap) => updatePill(snap.state));
monitor.start();Web Component attributes
| Attribute | Required | Description |
|--------------|----------|-----------------------------------------------------------------------------|
| api-base | yes | Origin of the ChatSuite API. |
| tel | yes | Phone number with leading +, e.g. +41764113232. |
| data-token | yes | API token (wa_*). Use a token scoped to this tel only. |
| auto-open | no | When "true", opens the QR modal automatically as soon as a QR is emitted. |
DOM events
The custom element re-emits monitor events as bubbling CustomEvents on itself:
| Event | detail |
|----------------------|---------------------------------------------------------|
| chatsuite:state | SessionSnapshot (every state or QR change). |
| chatsuite:error | { message: string }. |
SessionMonitor events
monitor.on('open', () => {}); // SSE stream connected
monitor.on('state', (snap) => {}); // any state or QR change
monitor.on('qr', (snap) => {}); // new QR rotated in
monitor.on('connected', (snap) => {}); // session reached ACTIVE
monitor.on('disconnected', (snap) => {});
monitor.on('error', ({ message }) => {});
monitor.on('close', () => {}); // monitor.stop() calledSessionSnapshot always carries qr, qrVersion, qrExpiresAt, state, and tel. Use qrVersion to dedupe renders — it strictly increases each time Baileys rotates the QR.
Auth
The package authenticates to the API with a wa_* token via Authorization: Bearer <token>. The same global authenticate + requireSessionAccess middleware that protects /api/v1/sessions/... covers the SSE endpoint, so the token is scoped by its phone number / session ID restrictions exactly like the rest of the API.
For browser consumers: prefer a token that is scoped to a single tel so embedding it in HTML reveals only the access that page needs.
CORS
The ChatSuite API CORS allowlist already includes https://chatsuite.akson.ch, https://www.myarmy.ch, and https://myarmy.ch. Other origins must be added to apps/api/src/config/cors.config.ts (or the CORS_ORIGIN env var) before the SSE stream will load cross-origin.
Cache-busting
The bundle is shipped from the API with Cache-Control: max-age=86400, so consumers can see a 24-hour stale window after a release. Append a version query (?v=<release-hash>) to the script src to force a refresh, or invalidate the CDN cache, or pin a specific version when one is published.
Build
pnpm --filter @akson/chatsuite-session-embed buildOutputs:
dist/chatsuite-session.js— iife bundle for<script>tag use.dist/index.mjs— ESM entry for bundlers, plusdist/index.d.ts.
Smoke test
pnpm --filter @akson/chatsuite-session-embed build
open packages/session-embed/examples/static.htmlThe example page shows a status pill bound to the MyArmy session and logs every state/QR change.
