Why a Voice‑AI Portfolio Will Get You Hired
If you’re a developer who’s already tinkered with NLP or speech‑to‑text, a portfolio that showcases real‑time text‑to‑speech (TTS) and voice cloning can set you apart from the crowd. Recruiters love to see that you can build production‑ready pipelines that turn text into natural‑sounding audio, especially in a world where voice assistants and chat‑bots are becoming standard in every product.
Below is a step‑by‑step guide to building a minimal yet impressive voice‑AI portfolio site. We’ll walk through the stack, show how to hook up a TTS service, add voice cloning, and finally deploy it on an affordable, beginner‑friendly host.
The Stack: What You’ll Need
| Layer | Tool | Why |
|---|---|---|
| Backend | Python (Flask) | Lightweight, great for quick REST APIs |
| TTS & Voice Cloning | ElevenLabs | State‑of‑the‑art neural voices, easy API |
| Frontend | React | Simple UI, fast dev experience |
| Hosting | Bluehost | One‑click WordPress + easy VPS, $3‑$5/month |
| Domain | Namecheap / GoDaddy | Cheap, auto‑renew, good DNS |
Pro tip: If you’re comfortable with Node.js, swap Flask for Express and keep the same API calls – the code is almost identical.
1. Set Up the ElevenLabs Account
ElevenLabs offers a generous free tier and a straightforward API. Sign up here: https://try.elevenlabs.io/kr07zfuqn1bp.
After creating an account, grab your API key from the dashboard. We’ll use this in our backend to authenticate requests.
2. Build a Tiny Flask API
Create a new folder voice-backend and run:
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install flask requests
Create app.py:
from flask import Flask, request, jsonify
import requests
import os
app = Flask(__name__)
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
ELEVENLABS_URL = "https://api.elevenlabs.io/v1/text-to-speech"
@app.route("/synthesize", methods=["POST"])
def synthesize():
data = request.get_json()
text = data.get("text", "")
voice_id = data.get("voice_id", "Rachel") # default voice
payload = {
"text": text,
"voice_settings": {"stability": 0.5, "similarity_boost": 0.75}
}
headers = {
"xi-api-key": ELEVENLABS_API_KEY,
"Content-Type": "application/json"
}
resp = requests.post(ELEVENLABS_URL, json=payload, headers=headers)
if resp.status_code != 200:
return jsonify({"error": resp.text}), resp.status_code
# ElevenLabs returns raw audio bytes
return resp.content, 200, {"Content-Type": "audio/mpeg"}
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Tip: Store your API key securely. In production, use environment variables or a secrets manager.
Run the server:
export ELEVENLABS_API_KEY="your_api_key_here"
python app.py
Your endpoint http://localhost:5000/synthesize now accepts POST requests with JSON payload {"text": "Hello world"} and streams back an MP3.
3. Add Voice Cloning (Optional)
If you want to demo a custom voice, ElevenLabs also supports voice cloning. The flow is:
- Upload an audio sample (at least 30 seconds).
- Let the model train (a few minutes).
- Use the returned
voice_idin your synth calls.
Sample curl to upload a sample:
curl -X POST "https://api.elevenlabs.io/v1/voices" \
-H "xi-api-key: $ELEVENLABS_API_KEY" \
-F "audio=@/path/to/sample.wav" \
-F "name=MyCustomVoice"
The response gives you a voice_id. Use that in the voice_id field when calling /synthesize.
Pro tip: Store the custom
voice_idin a config file or database so you can swap voices without touching code.
4. Build a React Frontend
Create a new React app (using Vite or Create‑React‑App). Inside src/App.js:
import { useState } from "react";
export default function App() {
const [text, setText] = useState("");
const [audioUrl, setAudioUrl] = useState("");
const synthesize = async () => {
const res = await fetch("/api/synthesize", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text })
});
if (!res.ok) {
alert("Error synthesizing");
return;
}
const blob = await res.blob();
setAudioUrl(URL.createObjectURL(blob));
};
return (
<div style={{ padding: "2rem" }}>
<h1>Voice AI Portfolio Demo</h1>
<textarea
rows="4"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type something..."
style={{ width: "100%" }}
/>
<button onClick={synthesize}>Speak!</button>
{audioUrl && (
<div style={{ marginTop: "1rem" }}>
<audio controls src={audioUrl} />
</div>
)}
</div>
);
}
Proxy Setup (React dev server):
Add to vite.config.js:
export default defineConfig({
server: {
proxy: {
"/api": "http://localhost:5000"
}
}
});
Now, running npm run dev will give you a live preview at localhost:5173. When you type text and hit “Speak!”, the request goes to your Flask backend, which streams back a natural‑sounding MP3.
5. Deploy with Bluehost
Bluehost is the easy, affordable way to deploy a small web app. Here’s a quick checklist:
- Sign up: https://bluehost.sjv.io/5k0d52. The link offers a discounted introductory rate.
- Choose a plan: For a portfolio, the “Basic” plan ($3.95/month) is enough. It gives you a free domain for the first year and 50 GB of storage.
-
Upload your code:
- Use Bluehost’s cPanel →
File Manageror an FTP client. - Place the Flask app under
/public_html/voice-backend. - Install Python via cPanel’s “Setup Python App” and set the entry point to
app.py.
- Use Bluehost’s cPanel →
-
Set environment variables: In the Python app interface, add
ELEVENLABS_API_KEYwith your secret. -
Domain: Point your custom domain (e.g.,
voiceportfolio.com) to Bluehost’s nameservers (the same link gives you DNS info). - SSL: Bluehost includes free Let’s Encrypt SSL, so your site will be HTTPS out of the box.
Why Bluehost?
- One‑click WordPress installs (great if you want a blog side‑by‑side).
- 24/7 support and a user‑friendly interface for beginners.
- Cheap, reliable uptime – perfect for a portfolio that recruiters will visit.
6. Test, Iterate, and Showcase
-
Unit test your Flask route with
pytestorunittest. -
Measure latency: ElevenLabs is fast, but network hops add a few milliseconds. Use Chrome DevTools or
curl -w "@curl-format.txt"to log timings. - Add UI polish: Use Tailwind CSS or Bootstrap to make the page look professional.
- Add a “Demo” button that pre‑loads a short script (e.g., “Hello, I’m a voice‑AI developer”) so recruiters can hit “Speak!” right away.
- Export a video: Record the page and voice playback. Upload it to YouTube or Vimeo and link it from your LinkedIn profile.
7. Next Steps
- Add more voices: Use ElevenLabs’ voice catalog to demo multiple accents or languages.
- Implement a “Voice Clone” UI: Let users upload a short clip and see the result.
- Deploy on a VPS: For more control, switch to a DigitalOcean droplet or AWS Lightsail and use Nginx + Gunicorn.
- Add analytics: Use Google Analytics to see how many times the “Speak” button is pressed.
- Write a blog post: Explain the architecture, share code, and link back to your deployed site.
Call to Action
Ready to show recruiters that you can turn text into lifelike speech?
- Try ElevenLabs today and unlock high‑quality voices with their free tier: https://try.elevenlabs.io/kr07zfuqn1bp.
- Deploy your portfolio on Bluehost for just a few dollars a month and get a free domain: https://bluehost.sjv.io/5k0d52.
Build, deploy, and let the voice speak for you. Happy coding!
Top comments (0)