---
title: "Node.js Demo App"
section: "Real-time translation"
order: 3
sidebarLabel: "Node.js demo app"
parent: "Integrations"
---
This is a minimal working example that demonstrates real-time speech translation in a browser.
https://github.com/pinch-eng/pinch-realtime-demo
## Quick Start
#### 1. Clone the repository
```bash
git clone https://github.com/pinch-eng/pinch-realtime-demo
cd pinch-realtime-demo
```
#### 2. Install Dependencies
```bash
npm install
```
#### 3. Add Your API Key
Create a `.env` file in the project root:
```text
PINCH_API_KEY=your_api_key_here
```
Don't have an API key? Login to the [Pinch Developer Portal >](https://portal.startpinch.com/dashboard/developers)
#### 4. Run the Demo
```bash
npm start
```
You'll see:
EXAMPLE OUTPUT
Pinch Real-Time Demo running at http://localhost:3000
#### 5. Try It Out
1. Open your browser to `http://localhost:3000`
2. Click the **Connect** button
3. Allow microphone access when prompted
4. Start speaking and watch the real-time translation appear!
## How It Works
The demo has two simple parts:
**Backend (server.js)**
- Express server that runs on your computer
- Proxies requests to the Pinch API (keeps your API key secret)
- Serves the HTML file to your browser
**Frontend (index.html)**
- Single HTML file with embedded JavaScript
- Connects to the translation service
- Captures microphone audio and sends it for translation
- Displays transcripts and plays translated audio
## Understanding the Code
#### Session Creation (Backend)
The backend creates a secure session:
```jsx
// server.js
app.post("/api/session", async (req, res) => {
const response = await fetch("https://api.startpinch.com/api/beta1/session", {
method: "POST",
headers: {
"Authorization": `Bearer ${PINCH_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
source_language: "en-US",
target_language: "es-ES",
voice_type: "clone"
})
});
const data = await response.json();
res.json(data);
});
```
#### Connecting to the Room (Frontend)
```jsx
// Get credentials from backend
const { url, token } = await fetch("/api/session", {
method: "POST"
}).then(r => r.json());
// Connect to LiveKit room
const room = new Room();
await room.connect(url, token);
// Start streaming microphone
await room.localParticipant.setMicrophoneEnabled(true);
```
#### Receiving Transcripts (Frontend)
The browser listens for transcript messages:
```jsx
room.on(RoomEvent.DataReceived, (payload) => {
const message = JSON.parse(new TextDecoder().decode(payload));
if (message.type === "original_transcript") {
// Display original text in left panel
displayOriginal(message.text, message.is_final);
}
else if (message.type === "translated_transcript") {
// Display translation in right panel
displayTranslated(message.text, message.is_final);
}
});
```
#### Receiving Audio (Frontend)
The browser plays translated audio automatically:
```jsx
room.on(RoomEvent.TrackSubscribed, (track) => {
if (track.kind !== Track.Kind.Audio) return;
// Create audio element
const audioEl = document.createElement("audio");
audioEl.autoplay = true;
audioEl.playsInline = true;
// Attach translated audio stream
track.attach(audioEl);
document.body.appendChild(audioEl);
});
```
#### Change Languages
Edit `server.js` to translate between different languages:
```jsx
body: JSON.stringify({
source_language: "en-US", // Change this
target_language: "es-ES", // Change this
voice_type: "clone"
})
```
Check [Supported languages >](/docs/supported-languages) for the full list.