@monoverse/voicebot-vue
v0.8.0
Published
Vue 3 wrapper for the VoiceBot talking widget — drop the deployed pk_ embed onto a Vue or Nuxt app.
Downloads
394
Maintainers
Readme
@monoverse/voicebot-vue
A tiny, production-grade Vue 3 wrapper for the VoiceBot talking widget. Drop a voice (or chat) assistant onto your Vue or Nuxt app with one component and your public key.
This package is a thin injector over the already-deployed VoiceBot browser embed. It loads
the CDN bundle, hands it your pk_ public key, and the deployed widget self-bootstraps:
exchanges the pk_ (+ the browser-set Origin) for an origin-locked session token and mounts,
grounded in your store's catalog. There is no widget code in this package and no merchant
backend is required.
Install
npm install @monoverse/voicebot-vuevue (^3.4) is a peer dependency.
Usage
Render <VoiceBotWidget> once, near the root of your app.
<script setup lang="ts">
import { VoiceBotWidget } from '@monoverse/voicebot-vue';
</script>
<template>
<YourApp />
<VoiceBotWidget public-key="pk_live_xxx" />
</template>Voice or chat
<VoiceBotWidget public-key="pk_live_xxx" variant="voice" /> <!-- default -->
<VoiceBotWidget public-key="pk_live_xxx" variant="chat" />voice loads widget-voice.js; chat loads widget-chat.js.
Props & events
| Prop / event | Type | Default | Description |
| -------------- | -------------------------- | ------------------------------------ | ------------------------------------------------------------------ |
| public-key | string (required) | — | Your pk_ publishable key. |
| variant | 'voice' \| 'chat' | 'voice' | Which widget bundle to load. |
| script-src | string | https://api.monoverse.tech/widget | Override the CDN base (self-hosted API). Also sets data-api-base.|
| @error | (error: Error) => void | — | Emitted on script load failure or an empty public-key. |
Reactivity
The VoiceBot widget core is a one-per-page singleton — one mounted instance owns a single session token, WebSocket, and microphone. The wrappers document one consistent model:
- This package (Vue) reads props at mount and is one-shot: it deliberately does not
re-inject when a prop changes (that would mint a duplicate token + WS). To switch the key at
runtime, remount the host (a
:keychange orv-iftoggle).useVoiceBotbehaves identically. - The Next wrapper is likewise one-shot (
next/scriptcaches the tag bysrc). The React wrapper instead re-injects whenpublicKey,variant, orscriptSrcchange.
Composable (imperative)
For custom layouts, useVoiceBot runs the same lifecycle without rendering an element. Call it
inside setup() (it registers onMounted / onBeforeUnmount internally):
<script setup lang="ts">
import { useVoiceBot } from '@monoverse/voicebot-vue';
useVoiceBot({ publicKey: 'pk_live_xxx', variant: 'chat' });
</script>Nuxt
The component is SSR-safe: it injects the script in onMounted (which never runs on the server)
and the embed itself guards window/document, so a server render is a no-op that never throws.
On Nuxt, render it client-side only so the widget code runs only in the browser:
<template>
<ClientOnly>
<VoiceBotWidget public-key="pk_live_xxx" />
</ClientOnly>
</template>Provisioning your pk_
pk_ is issued server-side by a VoiceBot operator (a repo script — seed_public_key.py).
When the key is issued, you list the exact origins allowed to use it:
- List every origin explicitly.
https://shop.example,https://www.shop.example, andhttps://app.shop.exampleare three different origins. wwwand subdomains are not inherited — register each separately.- An origin is
scheme://host[:port].http≠https; a non-default dev port is part of the origin (e.g.http://localhost:5173). Register your dev origins too. - Wildcards are not supported.
If the widget does not appear, the current origin is almost always missing from the key's
allow-list — the token mint returns 403 and the widget silently does not mount (your page is
never broken). See the provisioning guide.
Security
pk_ is a public, origin-locked key — exactly like a Stripe publishable key. Shipping it in
your client bundle is safe and intended:
- The mint endpoint issues a token only if the browser-set
Originis in the key's allow-list; another site copying yourpk_gets a403. tenant_idis resolved server-side from thepk_and signed into the token claim — the client never sends it, so cross-tenant access is structurally impossible.- The WebSocket upgrade re-checks
Originagainst the token claim and closes (4403) on mismatch.
The paired secret sk_ (catalog/order sync HMAC) is never in the browser — that is a
separate server-to-server flow, unrelated to this package.
Scope: what works now vs. the next tier
Works now with this package — a consultant grounded in your catalog: it answers product questions, recommends items, and describes your shipping and payment options from your store data.
Next tier (not in this package) — first-party actions: routing add_to_cart,
navigation, or other writes into your own app state. That needs the handler-registration SDK
(createWidget + merchant executors, ADR-053 / T5), which is a separate, heavier package and is
out of scope here. This wrapper is a script injector, not an action bridge.
License
MIT
