> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.jambonz.org/sdks/webrtc-web/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.jambonz.org/_mcp/server.
# Web (React) Guide
This guide walks you through building a voice calling application in the browser using React.
## Step 1: Create a React Project
```bash
npm create vite@latest my-jambonz-app -- --template react-ts
cd my-jambonz-app
```
## Step 2: Install the SDK
```bash
npm install @jambonz/client-sdk-web
```
## Step 3: Connect to the SBC
Create a component that connects to your jambonz SBC:
```tsx
// src/App.tsx
import { useState } from 'react';
import { createJambonzClient, ClientState } from '@jambonz/client-sdk-web';
function App() {
const [client, setClient] = useState(null);
const [state, setState] = useState(ClientState.Disconnected);
const connect = async () => {
const c = createJambonzClient({
server: 'wss://sbc.example.com:8443',
username: 'your-username',
password: 'your-password',
});
c.on('stateChanged', (s) => setState(s));
c.on('error', (err) => console.error('Error:', err.message));
await c.connect();
setClient(c);
};
return (
Status: {state}
);
}
export default App;
```
Run `npm run dev` and click **Connect**. You should see the status change to `registered`.
## Step 4: Make an Outbound Call
Add a call button to your component:
```tsx
const [call, setCall] = useState(null);
const [callState, setCallState] = useState(null);
const makeCall = () => {
const newCall = client.call('+15551234567');
newCall.on('stateChanged', (s) => setCallState(s));
newCall.on('accepted', () => console.log('Call connected'));
newCall.on('ended', (cause) => {
console.log('Call ended:', cause.reason);
setCall(null);
setCallState(null);
});
setCall(newCall);
};
// In your JSX:
Call: {callState || 'none'}
```
## Step 5: Handle Incoming Calls
Listen for incoming calls and show an answer/decline UI:
```tsx
const [incomingCall, setIncomingCall] = useState(null);
// Add this after creating the client:
c.on('incoming', (call) => {
setIncomingCall(call);
});
// In your JSX:
{incomingCall && (
Incoming call from: {incomingCall.remoteIdentity}
)}
```
## Step 6: Add Call Controls
Add mute, hold, and DTMF:
```tsx
const [isMuted, setIsMuted] = useState(false);
const [isHeld, setIsHeld] = useState(false);
// Listen for events:
newCall.on('mute', (muted) => setIsMuted(muted));
newCall.on('hold', (held) => setIsHeld(held));
// In your JSX:
```
## Step 7: Using React Hooks (Alternative)
Instead of managing state manually, use the built-in hooks:
```tsx
import { useJambonzClient, useCall } from '@jambonz/client-sdk-web';
function Phone() {
const client = useJambonzClient({
server: 'wss://sbc.example.com:8443',
username: 'your-username',
password: 'your-password',
});
const call = useCall(client.client);
return (
);
}
```
## Run the Full Example App
The repo includes a complete softphone example built with React + Vite + Tailwind CSS — with a polished dark theme UI, DTMF pad, incoming call handling, and console logs.
```bash
# 1. Clone the repo
git clone https://github.com/jambonz/webrtc-sdk.git
cd webrtc-sdk
# 2. Install and build the SDK
npm install
npm run build
# 3. Install and run the web example
cd examples/web
npm install
npm run dev
```
Open [http://localhost:5173](http://localhost:5173) in your browser.
#### What the example includes
The example app has clean separation between SDK logic and UI:
* **`src/useJambonz.ts`** — all SDK interactions (connect, call, mute, hold, transfer, incoming calls). **Read this file to learn the SDK.**
* **`src/App.tsx`** — wires SDK state to UI components
* **`src/components/`** — reusable UI: ConnectionForm, DialerView, ActiveCallView, IncomingCallView, DtmfPad, LogPanel
#### How to use it
1. Enter your jambonz SBC WebSocket URL (e.g. `wss://sbc.example.com:8443`)
2. Enter your SIP username and password
3. Click **Connect** — status dot turns green when registered
4. Enter a number or SIP URI and click **Call**
5. Use the in-call controls: mute, hold, DTMF pad, hang up
6. Incoming calls show an answer/decline screen
7. Expand **Console Logs** at the bottom to see SDK events
Source: [github.com/jambonz/webrtc-sdk/tree/main/examples/web](https://github.com/jambonz/webrtc-sdk/tree/main/examples/web)
> Build a browser softphone with the jambonz WebRTC SDK