Making Your Website Talk (Without Scaring Your Users)
Source: Dev.to

Introduction
Let’s be honest: most websites are too quiet. We spend our lives staring at glowing rectangles, reading text like it’s 1995. But your browser has a hidden superpower called the Web Speech API. It can talk. And no, I don’t mean those weird auto‑playing video ads from 2008.

Today, we’re building a Weather Dashboard that doesn’t just show you the temperature—it summarises the vibes and reads them to you.
The Stack
- React.js – for components and state management.
- Web Speech API – specifically
window.speechSynthesis. - OpenWeatherMap API – for weather data (or any weather API of your choice).
1. The “Brains”: Fetching & Summarising
First, we need something worth saying. A raw JSON response like {"temp": 273.15} is great for machines, but humans prefer “It’s freezing, stay inside.”
const fetchWeatherSummary = async (city) => {
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=YOUR_API_KEY&units=metric`
);
const data = await response.json();
// A simple summarizer (you could pipe this to an LLM for more “flavour”)
return `Currently in ${data.name}, it's ${data.main.temp} degrees with ${data.weather[0].description}. My professional advice? ${data.main.temp > 25 ? "Wear a hat." : "Grab a jacket."}`;
};
2. The “Voice”: Meet SpeechSynthesis
The window.speechSynthesis controller manages the queue of “utterances” (the things you want to say).
The useSpeech Hook
Wrap the speech engine in a clean React hook to keep UI logic tidy.
import { useState, useEffect } from 'react';
export const useSpeech = () => {
const [voices, setVoices] = useState([]);
useEffect(() => {
const updateVoices = () => setVoices(window.speechSynthesis.getVoices());
window.speechSynthesis.onvoiceschanged = updateVoices;
updateVoices();
}, []);
const speak = (text: string, voiceName?: string, rate = 1, pitch = 1) => {
// Cancel any ongoing chatter
window.speechSynthesis.cancel();
const utterance = new SpeechSynthesisUtterance(text);
// Choose voice or fall back to default
if (voiceName) {
utterance.voice = voices.find(v => v.name === voiceName) || null;
}
utterance.rate = rate; // 0.1 to 10
utterance.pitch = pitch; // 0 to 2
window.speechSynthesis.speak(utterance);
};
return {
speak,
voices,
pause: () => window.speechSynthesis.pause(),
resume: () => window.speechSynthesis.resume(),
};
};
Dashboard Component
Glue everything together with a button that fetches the data and reads it out loud.
import React, { useState } from 'react';
import { useSpeech } from './hooks/useSpeech';
const WeatherDashboard = () => {
const [summary, setSummary] = useState("");
const { speak, voices } = useSpeech();
const handleWeatherUpdate = async () => {
const text = await fetchWeatherSummary("London");
setSummary(text);
speak(text, voices[0]?.name, 1.1, 1);
};
return (
<div>
<h2>Weather Talker</h2>
<button onClick={handleWeatherUpdate}>Get Audio Summary</button>
{summary && (
<p>"{summary}"</p>
)}
</div>
);
};
export default WeatherDashboard;
Pro‑Tips for the Speech API
- Voices are lazy – they don’t always load immediately. The
onvoiceschangedevent in the hook ensures thevoicesarray is populated. - User activation required – browsers block audio that isn’t triggered by a user gesture. Call
speak()inside a click handler or similar event. - Shortcut library – the NPM package vocalize.ts provides a TypeScript‑first wrapper around the API. It’s currently in a low‑maintenance state, but the core logic works well.
Why Bother?
Accessibility is the obvious answer. Screen readers are great, but a specific “Read this for me” feature can help multitasking users or those with vision impairments.
It’s also just fun to make your computer talk back to you. Just don’t give it a sarcastic personality unless you’re prepared for the consequences.
Happy coding!