Dev.to WebDev 🛠 Dev 👁 0 📖 5 min read

Build and Host a Text-to-Speech SaaS with Node.js and Bluehost

Why a Text‑to‑Speech SaaS? Voice AI is moving from niche research labs into everyday products—think audiobooks, interactive assistants, and personalized voicemail. Building a text‑to‑speech (TTS) SaaS lets you package

Why a Text‑to‑Speech SaaS?

Voice AI is moving from niche research labs into everyday products—think audiobooks, interactive assistants, and personalized voicemail. Building a text‑to‑speech (TTS) SaaS lets you package that power for other developers or businesses, and with modern APIs you can have a production‑ready service up in a day.

In this walkthrough you’ll:

  1. Spin up a lightweight Node.js API that forwards text to a TTS engine and streams back an audio file.
  2. Integrate ElevenLabs, one of the most realistic voice‑cloning platforms on the market.
  3. Deploy the whole thing on Bluehost, the affordable, beginner‑friendly host that supports Node.js out of the box.

Everything is written for developers who already know the basics of JavaScript, so feel free to skim the sections you’re familiar with.

1. Set Up Your Project

# Create a new folder and initialise npm
mkdir tts-saas && cd tts-saas
npm init -y

# Install the required packages
npm i express axios dotenv
  • express – tiny web framework to expose a REST endpoint.
  • axios – simple HTTP client for calling the ElevenLabs API.
  • dotenv – keep your API keys out of source control.

Create a .env file (add this to .gitignore later):

ELEVENLABS_API_KEY=your_elevenlabs_api_key_here
PORT=3000

Pro tip: Sign up for an account at ElevenLabs and grab your API key from the dashboard. The free tier already gives you high‑quality neural voices.

2. The Core TTS Endpoint

Create index.js and paste the following code. It accepts a JSON payload with text and an optional voice_id. If no voice is supplied we fall back to the default “Rachel” voice that ElevenLabs provides.

require('dotenv').config();
const express = require('express');
const axios = require('axios');
const app = express();

app.use(express.json());

const ELEVENLABS_ENDPOINT = 'https://api.elevenlabs.io/v1/text-to-speech';
const DEFAULT_VOICE = 'EXAVITQu4vr4xnSDxMaL'; // Rachel

app.post('/api/tts', async (req, res) => {
  const { text, voice_id } = req.body;

  if (!text) {
    return res.status(400).json({ error: 'Missing "text" field' });
  }

  try {
    const response = await axios({
      method: 'post',
      url: `${ELEVENLABS_ENDPOINT}/${voice_id || DEFAULT_VOICE}`,
      headers: {
        'xi-api-key': process.env.ELEVENLABS_API_KEY,
        'Content-Type': 'application/json',
        Accept: 'audio/mpeg',
      },
      data: {
        text,
        voice_settings: {
          stability: 0.75,
          similarity_boost: 0.85,
        },
      },
      responseType: 'stream',
    });

    // Stream the MP3 straight back to the client
    res.set('Content-Type', 'audio/mpeg');
    response.data.pipe(res);
  } catch (err) {
    console.error(err.response?.data || err.message);
    res.status(500).json({ error: 'TTS generation failed' });
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`🚀 TTS service listening on port ${PORT}`));

How It Works

  1. Receive a request – The client sends plain text (and optionally a voice ID).
  2. Call ElevenLabs – The axios request forwards the text to the ElevenLabs /text-to-speech endpoint, asking for an MP3 stream.
  3. Pipe the result – Instead of buffering the whole file, we pipe the streaming response directly to the HTTP client. This keeps memory usage low and makes the API feel instantaneous.

You can test locally with curl:

curl -X POST http://localhost:3000/api/tts \
  -H "Content-Type: application/json" \
  -d '{"text":"Hello, world! This is my first voice‑AI service."}' \
  --output hello.mp3

If everything went well, hello.mp3 will contain a natural‑sounding voice generated by ElevenLabs.

3. Adding Voice Cloning (Optional)

ElevenLabs also offers voice cloning – you upload a few seconds of a speaker’s audio and receive a unique voice_id. To keep this article concise we won’t dive into the cloning flow, but the same /text-to-speech/{voice_id} endpoint works with the IDs you obtain from the cloning dashboard. Just swap the voice_id field in the request body.

4. Deploying to Bluehost

Now that the service runs locally, let’s get it online. Bluehost provides an affordable, one‑click Node.js setup on its shared‑hosting plans, and the control panel even lets you set environment variables without touching the server.

4.1. Spin Up a Bluehost Account

  1. Go to the Bluehost sign‑up page: https://bluehost.sjv.io/5k0d52.
  2. Choose the “Basic” plan (or a higher tier if you expect heavy traffic).
  3. During checkout you’ll get a free domain for the first year – perfect for a SaaS demo.

4.2. Upload Your Code

Bluehost’s cPanel → File Manager works like any FTP client:

  • Create a folder called tts-saas inside the public_html directory.
  • Upload index.js, package.json, .env, and a node_modules zip (or just run npm install via the SSH terminal – see next step).

4.3. Enable Node.js

  1. In cPanel, locate “Setup Node.js App”.
  2. Click Create Application, select the Node version you prefer (v18+ is recommended), and set the Application Root to the folder you just created.
  3. Set the Startup File to index.js.
  4. Add the environment variable ELEVENLABS_API_KEY with the value from your ElevenLabs dashboard.
  5. Click Run – Bluehost will install dependencies and start the process for you.

4.4. Point a Subdomain (Optional)

If you want a clean URL like api.myttsapp.com, go to “Domains → Subdomains”, create the subdomain, and then edit the Node.js app to use that path as the Application URL.

That’s it! Your TTS SaaS is now reachable at https://yourdomain.com/api/tts. Because the service streams MP3 directly, you can embed it in any front‑end framework (React, Vue, plain HTML) with a simple <audio> tag.

5. Scaling Thoughts

  • Caching – For frequently requested phrases, store the MP3 on the server or a CDN (Bluehost offers Cloudflare integration).
  • Rate limiting – Use a middleware like express-rate-limit to protect your ElevenLabs quota.
  • Billing – If you plan to monetize, add an API key system and track usage per client.

All of these can be added without changing the core endpoint we built.

6. TL;DR – What You Need

Component Provider Why It’s Chosen
Text‑to‑Speech Engine ElevenLabs Industry‑leading neural voices, simple REST API, free tier for prototyping
Hosting / Deployment Bluehost Easy one‑click Node.js setup, affordable plans, built‑in domain management
Framework Express (npm) Minimal boilerplate, perfect for a micro‑service
HTTP Client Axios (npm) Handles streaming responses cleanly

7. Next Steps

  • Add authentication (JWT, API keys).
  • Expose more voice parameters (speed, pitch) via query strings.
  • Build a tiny front‑end that lets users type text and hear the result instantly.

The skeleton is now in place, and because you’re using a reputable host and a top‑tier voice provider, you can focus on product features instead of infrastructure headaches.

🎤 Ready to Give Your App a Voice?

If you’re excited about building voice‑first experiences, start by signing up for an ElevenLabs account at https://try.elevenlabs.io/kr07zfuqn1bp. Once you have your API key, spin up a Bluehost server with https://bluehost.sjv.io/5k0d52 and follow the steps above. In under an hour you’ll have a fully functional, production‑ready TTS SaaS that you can showcase to clients or integrate into your own products.

Happy coding, and may your apps always speak clearly!

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.