Svelte and other frameworks
Svelte, Solid, Lit, Qwik and plain JavaScript need no wrapper: load and start Nexafon once in the browser, then write
the <nexafon-*> elements in your markup.
npm install @nexafon/js<script lang="ts">import { loadNexafon, type NexafonApi } from '@nexafon/js'import { onMount } from 'svelte'
const getUserToken = async () => { const r = await fetch('/api/nexafon-token', { method: 'POST' }) if (!r.ok) throw new Error(`The token endpoint answered ${r.status}`) return r.text()}
// Svelte uses the Web Components directly: start Nexafon once in the browser, then write the elements.onMount(() => { let nexafon: NexafonApi | undefined loadNexafon().then((api) => { nexafon = api?.init({ publishableKey: import.meta.env.VITE_NEXAFON_PUBLISHABLE_KEY, getUserToken, }) }) return () => nexafon?.destroy()})</script>
<main class="support"> <nexafon-inbox style="height: 640px"></nexafon-inbox> <aside> <nexafon-call-button phone="+252615550142"></nexafon-call-button> <nexafon-softphone></nexafon-softphone> </aside></main>
<style> .support { display: grid; gap: 16px; padding: 16px; grid-template-columns: 1fr 340px; }</style>loadNexafon() resolves to null on the server, so the same code is safe in SvelteKit, SolidStart or Astro server
code. With TypeScript JSX (Solid), declare the nexafon-* tags in JSX.IntrinsicElements.
The token endpoint
Section titled “The token endpoint”getUserToken calls your server, which signs a token with a server helper. The example’s
POST /api/nexafon-token handler:
import type { IncomingMessage, ServerResponse } from 'node:http'import { createUserToken } from '@nexafon/node'
interface SignedInUser { id: string name: string role: string email: string emailVerified: boolean isStaff: boolean}
// Your app's own session decides who is signed in, and its own records whether it has confirmed their email. The// example has no sign-in: EXAMPLE_DEMO_USER_EMAIL is a demo user for local runs only, so replace this with your session.function signedInUser(_req: IncomingMessage): SignedInUser | null { const email = process.env.EXAMPLE_DEMO_USER_EMAIL if (!email) return null return { id: 'demo-user-1', name: 'Demo User', role: process.env.EXAMPLE_DEMO_USER_ROLE || 'agent', email, // The demo address is a member you invited, so you have confirmed it. emailVerified: true, isStaff: true, }}
// Everyone who gets a token may reach your workspace's inbox and calls: sign only for your staff, never for customers// who signed up. The example's only user is the demo teammate.function mayUseNexafon(user: SignedInUser): boolean { return user.isStaff}
// POST /api/nexafon-token signs a token for the signed-in user with NEXAFON_SECRET_KEY.export function userToken(req: IncomingMessage, res: ServerResponse): void { if (req.method !== 'POST') { res.writeHead(405).end() return } const user = signedInUser(req) if (!user) { res.writeHead(401).end() return } if (!mayUseNexafon(user)) { res.writeHead(403).end() return } const token = createUserToken({ userId: user.id, name: user.name, role: user.role, email: user.email, // Nexafon links a first sign-in to the member with this email only when it is verified: never send true for an // address your app has not confirmed, or whoever sets a member's email on your app acts as that member. emailVerified: user.emailVerified, }) res.writeHead(200, { 'content-type': 'text/plain', 'cache-control': 'no-store' }).end(token)}signedInUser stands for your app’s own session: answer 401 when nobody is signed in. The example has no sign-in,
so on a local run it signs for the demo member named in EXAMPLE_DEMO_USER_EMAIL and answers 401 without one;
replace it with your session. mayUseNexafon answers 403 to signed-in users who must not use Nexafon: sign only for
your staff, never for customers who signed up, since a token can make its user a member of your workspace. The example
treats its demo user as staff.
The example mounts it as middleware of the Vite dev and preview servers in examples/svelte/vite.config.ts; in
production it is a route of your own server, behind your own session check.
The full example is examples/svelte.