Text-to-Speech LWC Guide – Browser-Based Voice for Salesforce

I recently had a client ask for a way to read out case updates for visually impaired users, and that’s when I realized how simple it is to build a Text-to-Speech LWC. You don’t need expensive third-party integrations or heavy libraries to make your Salesforce org talk to you. In fact, most modern browsers do the heavy lifting for us through the Web Speech API.

Why you should consider Text-to-Speech LWC for your next project

Most of the time, we think about accessibility as just high-contrast colors or screen reader support. But providing a native way for a user to hear text can be a huge win. I’ve seen teams use this for Experience Cloud portals to help users who might struggle with long blocks of text. It’s also a great way to add a bit of personality to your custom components.

And let’s be honest, with the push toward AI, voice is becoming the standard. If you’re looking into Agentforce use cases, having a component that can actually speak the agent’s response makes the whole experience feel much more natural. The best part? It’s all browser-based, so it doesn’t count against your Salesforce governor limits.

Building a basic Text-to-Speech LWC from scratch

Setting up a Text-to-Speech LWC is actually pretty straightforward. We use the speechSynthesis interface, which is part of the Web Speech API. You basically create an “utterance” (the text you want spoken), tell the browser which voice to use, and hit play. Here is how I usually structure the code.

The JavaScript logic

One thing that trips people up is that voices don’t always load immediately. You’ll want to make sure you check if the browser actually supports speech before trying to run the function. Here’s a clean way to handle the logic:

import { LightningElement, track } from 'lwc';

export default class TextToSpeechLwc extends LightningElement {
    @track textToSpeak = 'Welcome to the Salesforce ecosystem!';

    handleInputChange(event) {
        this.textToSpeak = event.target.value;
    }

    speak() {
        if (!window.speechSynthesis) {
            console.error('This browser does not support text-to-speech.');
            return;
        }

        // Always stop any current speech before starting new audio
        window.speechSynthesis.cancel();

        const utterance = new SpeechSynthesisUtterance(this.textToSpeak);
        utterance.lang = 'en-US';

        // Grab the available voices from the browser
        const voices = window.speechSynthesis.getVoices();
        if (voices.length > 0) {
            // I usually just grab the first English voice found
            utterance.voice = voices.find(v => v.lang.includes('en')) || voices[0];
        }

        window.speechSynthesis.speak(utterance);
    }
}

The HTML template

For the UI, you don’t need anything fancy. A simple textarea and a button will do the trick. If you’re building something more complex, you might even want to look at LWC component communication to trigger speech from a parent component.

<template>
    <lightning-card title="Voice Assistant" icon-name="utility:volume_high">
        <div class="slds-var-p-around_medium">
            <lightning-textarea 
                label="Enter text to hear it aloud" 
                value={textToSpeak} 
                onchange={handleInputChange}>
            </lightning-textarea>
            <lightning-button 
                label="Speak Now" 
                onclick={speak} 
                variant="brand" 
                class="slds-var-m-top_small">
            </lightning-button>
        </div>
    </lightning-card>
</template>

Real-world tips for the Text-to-Speech LWC

Look, just because you can make your app talk doesn’t mean it should talk all the time. Honestly, most teams get this wrong by making it too intrusive. Here’s what I’ve learned from implementing this in production orgs:

  • Don’t auto-play: Browsers usually block audio that starts without a user click anyway. Always wait for the user to trigger the speech.
  • Add a “Stop” button: There is nothing more annoying than a three-minute paragraph you can’t silence. Use window.speechSynthesis.cancel() to give users control.
  • Check for mobile: Safari on iOS can be a bit picky with the Web Speech API. Always test on a physical device, not just the Chrome emulator.
  • Language matters: If your users are global, don’t hardcode ‘en-US’. Grab the user’s locale from Salesforce and match the voice accordingly.

Pro Tip: The getVoices() method is often called asynchronously. If it returns an empty list the first time, you might need to listen for the voiceschanged event before selecting a voice.

Key Takeaways

  • A Text-to-Speech LWC is a browser-native way to improve accessibility without extra costs.
  • Use speechSynthesis.cancel() before every new utterance to prevent overlapping audio.
  • Always provide a clear UI control so users can start and stop the voice as they please.
  • This approach works great for Experience Cloud sites and custom internal tools.

So, is a Text-to-Speech LWC a “must-have” for every org? Probably not. But for specific accessibility needs or making your custom apps feel more modern, it’s a fantastic tool to have in your back pocket. It’s lightweight, easy to maintain, and requires zero server-side Apex logic. Give it a try in your sandbox and see how it changes the user experience.