The ThunderPhoneWidget component renders a ready-to-use call button with built-in controls for muting, ending the call, and displaying connection status. It is the fastest way to add voice AI to a React app.
Installation
npm install @thunderphone/widget
Basic Usage
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'
function App() {
return (
<ThunderPhoneWidget
apiKey="pk_live_your_publishable_key"
agentId={123}
/>
)
}
You must import the CSS file for the widget to render correctly. Without it, the widget will be unstyled.
Props
The component accepts the following props via ThunderPhoneWidgetProps:
| Prop | Type | Required | Description |
|---|
apiKey | string | Yes | Publishable API key (pk_live_...) from the Developers settings |
agentId | number | Yes | ID of the agent to connect to (must have Embeddable Widget enabled) |
apiBase | string | No | API base URL. Defaults to https://api.thunderphone.com/v1 |
onConnect | () => void | No | Called when the voice session successfully connects |
onDisconnect | () => void | No | Called when the session ends |
onError | (error) => void | No | Called on errors. The error object has error (code) and message fields |
className | string | No | Additional CSS class name applied to the widget container |
ringtone | boolean | string | No | Play a ringtone while connecting. true for the default ringtone, or a URL string for custom audio. Disabled by default |
Examples
With Event Callbacks
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'
function SupportWidget() {
return (
<ThunderPhoneWidget
apiKey="pk_live_your_publishable_key"
agentId={123}
onConnect={() => {
console.log('Voice session connected')
analytics.track('widget_call_started')
}}
onDisconnect={() => {
console.log('Voice session ended')
analytics.track('widget_call_ended')
}}
onError={(error) => {
console.error(`Widget error: ${error.error} - ${error.message}`)
}}
/>
)
}
With Custom Styling
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'
function BrandedWidget() {
return (
<ThunderPhoneWidget
apiKey="pk_live_your_publishable_key"
agentId={123}
className="my-custom-widget"
/>
)
}
.my-custom-widget .tp-button--start {
background-color: #4a90d9;
}
.my-custom-widget .tp-button--end {
background-color: #e74c3c;
}
See the Styling guide for all available CSS classes.
With Ringtone
Play a phone-ringing sound while the connection is being established:
import { ThunderPhoneWidget } from '@thunderphone/widget'
import '@thunderphone/widget/style.css'
function PhoneWidget() {
return (
<ThunderPhoneWidget
apiKey="pk_live_your_publishable_key"
agentId={123}
ringtone={true}
/>
)
}
Use a custom ringtone by passing an audio file URL:
<ThunderPhoneWidget
apiKey="pk_live_your_publishable_key"
agentId={123}
ringtone="https://example.com/my-ringtone.mp3"
/>
The ringtone loops while the widget is in the connecting state and fades out smoothly when the agent connects.
With Custom API Base
You only need to set apiBase if you are using a self-hosted or proxy API endpoint. The default points to https://api.thunderphone.com/v1.
<ThunderPhoneWidget
apiKey="pk_live_your_publishable_key"
agentId={123}
apiBase="https://your-proxy.example.com/v1"
/>
Error Handling
When the onError callback fires, it receives an error object with two fields:
| Field | Type | Description |
|---|
error | string | Machine-readable error code |
message | string | Human-readable error description |
Common error codes include domain not allowed, agent not found, and invalid API key.
Next Steps