1. Why ElevenLabs for Next.js?
If you’re building a web app that needs dynamic, high‑quality speech, you’ll quickly realize that most open‑source TTS engines feel a bit stale or lack the natural prosody that a real‑world user expects. ElevenLabs offers a cloud‑based API that delivers:
- Real‑time, neural‑network‑generated voice
- Voice cloning with just a few minutes of audio
- Low‑latency, REST‑friendly endpoints
In short, it’s the fastest way to add lifelike voice to a Next.js site without wrestling with heavy audio processing libraries.
Want to see it in action? Grab your free API key through this link: https://try.elevenlabs.io/kr07zfuqn1bp
2. Project setup
npx create-next-app elevenlabs-demo
cd elevenlabs-demo
npm install
We’ll use TypeScript for type safety, but the concepts apply to plain JavaScript as well.
touch tsconfig.json
Add a minimal tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
3. Store your ElevenLabs key
Create a .env.local file in the project root:
ELEVENLABS_API_KEY=sk_your_api_key_here
Next.js automatically loads .env.local, so you can reference it in your code via process.env.ELEVENLABS_API_KEY.
Remember, never commit
.env.localto version control.
4. Build an API route that talks to ElevenLabs
Next.js API routes give us a clean place to keep your secret key out of the client bundle.
// pages/api/synthesize.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { text, voiceId } = req.body;
if (!text || !voiceId) {
return res.status(400).json({ error: 'Missing text or voiceId' });
}
const apiKey = process.env.ELEVENLABS_API_KEY;
if (!apiKey) {
return res.status(500).json({ error: 'API key missing' });
}
const response = await fetch(
`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`,
{
method: 'POST',
headers: {
'xi-api-key': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
text,
voice_settings: {
stability: 0.75,
similarity_boost: 0.75,
},
}),
}
);
if (!response.ok) {
const error = await response.text();
return res.status(response.status).json({ error });
}
// ElevenLabs returns the audio as a binary stream
const audioBuffer = await response.arrayBuffer();
const buffer = Buffer.from(audioBuffer);
// Return the audio as a blob with proper headers
res.setHeader('Content-Type', 'audio/mpeg');
res.setHeader('Content-Length', buffer.length.toString());
res.send(buffer);
}
What’s happening here?
-
Validate input – we expect
textandvoiceId. - Call ElevenLabs – use the official REST endpoint.
- Stream back audio – the client can directly consume it.
5. Get a voice ID
ElevenLabs requires you to pick a voice ID. You can fetch available voices via their API:
curl -H "xi-api-key: $ELEVENLABS_API_KEY" \
https://api.elevenlabs.io/v1/voices
Pick an ID (e.g., EXAVITQu4vr4xnSDxMaL) and store it in a constant:
const DEFAULT_VOICE_ID = 'EXAVITQu4vr4xnSDxMaL';
6. Build the UI
A simple form that sends the text to the API and plays the resulting audio:
// pages/index.tsx
import { useState, useRef } from 'react';
export default function Home() {
const [text, setText] = useState('');
const [loading, setLoading] = useState(false);
const audioRef = useRef<HTMLAudioElement>(null);
const handleSpeak = async () => {
setLoading(true);
const res = await fetch('/api/synthesize', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text, voiceId: DEFAULT_VOICE_ID }),
});
if (res.ok) {
const blob = await res.blob();
const url = URL.createObjectURL(blob);
if (audioRef.current) {
audioRef.current.src = url;
audioRef.current.play();
}
} else {
const err = await res.text();
alert(`Error: ${err}`);
}
setLoading(false);
};
return (
<div style={{ padding: '2rem', fontFamily: 'sans-serif' }}>
<h1>ElevenLabs + Next.js Demo</h1>
<textarea
rows={4}
cols={60}
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type something to speak…"
style={{ width: '100%', marginBottom: '1rem' }}
/>
<br />
<button onClick={handleSpeak} disabled={loading}>
{loading ? 'Generating…' : 'Speak'}
</button>
<audio ref={audioRef} controls style={{ marginTop: '1rem' }} />
</div>
);
}
How it works
-
User types text – stored in
text. -
Click “Speak” – triggers
handleSpeak. - API call – sends the text to our serverless endpoint.
-
Play audio – the binary response is turned into a Blob URL and fed to an
<audio>element.
7. Voice cloning (optional but powerful)
If you want a custom voice, ElevenLabs lets you upload a short clip (≤ 5 min) and generate a new voice ID. Here’s a quick snippet to upload a clip:
curl -X POST https://api.elevenlabs.io/v1/voices \
-H "xi-api-key: $ELEVENLABS_API_KEY" \
-F "name=My Custom Voice" \
-F "file=@/path/to/clip.wav"
The response will include a new voice_id you can reuse in the synth endpoint. Once you have that, swap DEFAULT_VOICE_ID with your custom ID.
8. Deployment tips
- Serverless functions: The API route above works out‑of‑the‑box on Vercel, Netlify, or any platform that supports Next.js.
-
Environment variables: Store
ELEVENLABS_API_KEYsecurely in your deployment provider’s secret store. - CORS: Since the API route is on the same domain, you don’t need extra CORS headers.
9. Performance & cost
- Latency: ElevenLabs’ endpoint is low‑latency; most requests finish in < 300 ms.
- Pricing: They offer a free tier (limited characters per month). Beyond that, pricing is per‑character, which is competitive for most small‑to‑medium projects.
10. Final thoughts
Integrating ElevenLabs into a Next.js app is a breeze: one API route, a tiny form, and you’re ready to deliver rich, human‑like voice. Whether you’re building a voice‑enabled chatbot, an audiobook generator, or a voice‑clone demo, ElevenLabs gives you the audio fidelity you’d expect from a commercial product.
Ready to add voice to your Next.js project? Grab your free API key and start experimenting: https://try.elevenlabs.io/kr07zfuqn1bp
Happy coding, and may your apps sound amazing!
Top comments (0)