Embedded
Native feel inside your app. Drop React components and Web Components into your existing UI so voice feels like a built-in feature.
Prebuilt components handle WebRTC signaling, device permissions, audio routing, and reconnection. You keep full control over layout, navigation, and identity.
Component inventory
React (@dialstack/sdk/react)
| Component | Purpose |
|---|---|
<DialstackComponentsProvider> | Provides session and auth context for all child components. |
<CallLogs> | Displays a call history table (date, direction, duration, status, quality). |
<CallHistory> | Displays a compact recent-call list for sidebars and cards. |
<Voicemails> | Displays a voicemail list with audio playback, transcription, and delete. |
<PhoneNumbers> | Manages phone numbers for an account. |
<PhoneNumberOrdering> | Searches and orders new phone numbers. |
<DialPlan> | Renders a dial-plan graph (mode="view", "edit", or "preview"). |
useDialstack() | Exposes a headless hook for fully custom UIs on top of the same data. |
Web Components (@dialstack/sdk/pure)
Framework-agnostic versions for use from Vue, Svelte, Angular, or plain HTML:
| Component | Purpose |
|---|---|
<dialstack-call-logs> | Displays a call history table (date, direction, duration, status, quality). |
<dialstack-call-history> | Displays a compact recent-call list for sidebars and cards. |
<dialstack-voicemails> | Displays a voicemail list with audio playback, transcription, and delete. |
<dialstack-phone-numbers> | Manages phone numbers for an account. |
<dialstack-phone-number-ordering> | Searches and orders new phone numbers. |
Separate entry point
| Component | Entry | Purpose |
|---|---|---|
<OnboardingPortal> | @dialstack/sdk/onboarding | Provides a guided first-time setup wizard. Loads separately to keep the bundle small. |
Session token flow
Your backend mints a session, your frontend drops it into the provider, components authenticate transparently.
// Backend — /api/dialstack/session
import { DialStack } from '@dialstack/sdk/server';
const ds = new DialStack(process.env.DIALSTACK_KEY);
export default async function handler(req, res) {
const accountId = getAccountForUser(req); // your app's logic
const { client_secret } = await ds.accountSessions.create({ account: accountId });
res.json({ client_secret });
}
// Frontend
import { loadDialStack, DialstackComponentsProvider, CallLogs, Voicemails } from '@dialstack/sdk';
const dialstack = await loadDialStack('pk_live_YOUR_KEY', {
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session');
return res.json();
},
});
export function VoiceInbox() {
return (
<DialstackComponentsProvider dialstack={dialstack}>
<CallLogs />
<Voicemails />
</DialstackComponentsProvider>
);
}
The SDK refreshes the session token automatically before expiry. Session tokens are account-scoped and expire in one hour.
See Authentication for token lifecycle, revocation, and multi-account handling.
Theming
For a full list of CSS variables (colors, typography, spacing, shadows) and layout variants, see the Theming guide.
Pass an appearance block to initialize() / loadDialStack():
const dialstack = await loadDialStack('pk_live_YOUR_KEY', {
fetchClientSecret,
appearance: {
theme: 'auto', // 'light' | 'dark' | 'auto'
variables: {
colorPrimary: '#6B2CFF',
colorPrimaryHover: '#5A25D9',
fontFamily: 'Inter, system-ui, sans-serif',
borderRadius: '8px',
},
},
});
Per-component density:
<CallLogs layoutVariant="compact" />
<Voicemails layoutVariant="comfortable" />
Component embedding example
The <DialstackComponentsProvider> handles the session token lifecycle. Any child components you nest inside it automatically inherit the authenticated context, fetch their own data, and render fully functional views. Here is an example composing a sidebar and a main content area:
import {
loadDialStack,
DialstackComponentsProvider,
CallHistory,
PhoneNumbers,
} from '@dialstack/sdk';
const dialstack = await loadDialStack('pk_live_YOUR_KEY', {
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session');
const { client_secret } = await res.json();
return client_secret;
},
});
export function AccountDashboard() {
return (
<DialstackComponentsProvider dialstack={dialstack}>
<div style={{ display: 'flex', gap: '2rem' }}>
{/* Sidebar for recent activity */}
<aside style={{ width: 300 }}>
<CallHistory layoutVariant="compact" />
</aside>
{/* Main area for management */}
<main style={{ flex: 1 }}>
<h2>Phone Numbers</h2>
<PhoneNumbers />
</main>
</div>
</DialstackComponentsProvider>
);
}
When to pick this
- Voice lives inside a workflow your users already use daily (CRM, dispatcher, EHR).
- You want to control layout and navigation but not rebuild softphone internals.
- You have a React or modern front-end and want to ship in a few sprints.
When to pick something else
- If your customers prefer a dedicated phone portal (simpler onboarding, fewer surfaces) → White Label.
- If you're building a bespoke workflow that doesn't match any prebuilt component → Direct API.
See also
- SDK overview — distribution targets (
main,pure,server) and bundle sizes. - React components — per-component props and events.
- Web Components — framework-agnostic wrappers.
- Theming — full appearance surface.