Web SDK
The web SDK puts Nexafon’s screens inside any web page as Web Components. Each one renders a frame of Nexafon’s embed pages, so your page needs no UI code and always shows the current version. It works in every framework; the React, Vue and Angular wrappers add idiomatic components on top.
Load it
Section titled “Load it”With a script tag (the CDN serves the latest v1, with fixes and new features automatically):
<script src="https://app.nexafone.so/embed/v1/nexafon.js"></script>Or from npm, as a typed loader that adds the same script once:
npm install @nexafon/jsimport { loadNexafon } from '@nexafon/js'
// Resolves to null on the server (Next.js, Nuxt, Angular SSR, SvelteKit): it never touches window there.const Nexafon = await loadNexafon()Start it
Section titled “Start it”Call init once per page, before or after the elements are in the DOM:
Nexafon.init({ publishableKey: 'pk_live_…', getUserToken: async () => { const r = await fetch('/nexafon-token', { method: 'POST' }) if (!r.ok) throw new Error(`The token endpoint answered ${r.status}`) return r.text() }, appearance: { primaryColor: '#16A34A', radius: 10, colorMode: 'auto' }, locale: 'en', popOutCalls: false,})| Option | Type | |
|---|---|---|
publishableKey |
string | pk_live_…/pk_test_… for one business, or a partner’s ppk_live_…/ppk_test_… |
getUserToken |
() => Promise<string> | string |
Returns a fresh user token from your server each time; a token works once (user tokens). Throw when your server answers an error (such as 401 when no one is signed in), so the SDK never gets an error body as a token |
appearance |
object | Primary colour, radius, font and light/dark mode (appearance) |
locale |
'en' | 'so' | 'ar' |
The embedded screens’ language; Arabic renders right to left |
popOutCalls |
boolean | On multi-page sites, calls run in a small window so navigating does not end them |
init loads a hidden hub frame at once: it holds the session, the one realtime connection and the call audio for
the whole page, and every visible component shares it. So the first component appears in well under a second, and a
page with an inbox, a softphone and five call buttons still opens one connection.
Components
Section titled “Components”| Element | Shows | Attributes |
|---|---|---|
<nexafon-app> |
The whole dashboard with Nexafon’s side menu: inbox, calls, team, settings, billing, orders… (each section only for users whose role may open it) | store |
<nexafon-inbox> |
The shared WhatsApp inbox | store |
<nexafon-softphone> |
The softphone: incoming calls, dial pad, call controls | store |
<nexafon-call-button> |
A button that calls one customer on WhatsApp | phone (E.164, required), store |
store opens a partner’s store first, by its externalRef or workspace id (store switcher).
Changing an attribute reloads that component.
Size <nexafon-app> and <nexafon-inbox> yourself (they fill their element, at least 480 px high); the softphone and
the call button size themselves to their content. Frames get allow="microphone; autoplay; clipboard-write": the
browser asks for the microphone the first time a call starts.
Without custom elements you can mount the same screens imperatively:
const unmount = Nexafon.mount(document.getElementById('support'), { component: 'inbox' })// Nexafon.mount(el, { app: true }) for the whole dashboard; unmount() removes it again.Methods
Section titled “Methods”| Method | Does |
|---|---|
openChat(phone) |
Opens (or starts) the chat with that customer in the inbox or app on the page |
call(phone) |
Calls the customer on WhatsApp from the store the user viewed last; with popOutCalls the call opens in the pop-out window |
startInternalCall(memberIds) |
Starts a team call with those members |
setAppearance(appearance) |
Changes colours, radius, font or mode at once, for example when your own theme switches |
on(event, listener) / off(event, listener) |
Listen to events; on returns a function that stops listening |
destroy() |
Removes every frame and ends the session on this page |
Methods that act through a frame return a Promise that rejects when the action is not possible, such as a call without a microphone.
Calls across page navigation
Section titled “Calls across page navigation”On a classic multi-page site a page load would cut an active call. With popOutCalls: true a call opens in a small
pop-out window that survives navigation; a call already live on the page can move into it and back. If the browser
blocks the pop-up, the call stays on the page and the user is asked to allow pop-ups. The
HTML example shows it across two pages.
Security model
Section titled “Security model”- The publishable key starts sessions only from its allowed origins, and Nexafon’s frames load only on the
workspace’s embed domains (CSP
frame-ancestors). - Every message between your page and the frames is origin-checked and versioned.
- Session tokens never reach your page: no
localStorage,sessionStorageor cookies on your site.
See security for the Content-Security-Policy your own page needs.