#11745: ui: add server-side TTS for web chat via gateway endpoint
docs
app: web-ui
gateway
stale
Cluster:
Model Reasoning Fixes
## Summary
- Add `POST /api/tts/synthesize` gateway endpoint that uses the existing Edge TTS infrastructure (Microsoft neural voices — free, no API key needed) to synthesize speech server-side
- Update the web chat UI to try server-side TTS first via `fetch` → blob → `HTMLAudioElement`, falling back to browser Speech API on any error
- Pass gateway URL and token from app settings to the chat TTS module so it can reach the endpoint
## Test plan
- [ ] Start gateway, open web chat, enable TTS (speaker button), send a message — verify audio plays with natural Edge TTS voice
- [ ] Check network tab for `POST /api/tts/synthesize` returning `audio/mpeg`
- [ ] Stop gateway, verify browser Speech API fallback kicks in
- [ ] Verify unauthenticated requests to `/api/tts/synthesize` return 401
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR adds a new authenticated gateway endpoint (`POST /api/tts/synthesize`) that synthesizes speech server-side using the existing Edge TTS infrastructure, returning an `audio/mpeg` payload. The web chat UI is updated to prefer this server-side TTS path (fetch → Blob → `HTMLAudioElement`) and to fall back to the browser Speech API on any errors. The UI wiring also passes the gateway base URL and token from app settings into the chat TTS module, and includes minor supporting UI/CSS/icon updates.
This fits into the existing architecture by extending the gateway’s HTTP server routing with a TTS handler module, and by keeping client-side speech as a fallback for environments where the gateway is unavailable or blocked.
<h3>Confidence Score: 3/5</h3>
- This PR is close, but needs fixes in the new TTS streaming and browser playback path before it’s safe to merge.
- The gateway endpoint streams audio without handling read-stream errors, which can hang responses or throw unhandled errors. The endpoint also hardcodes `audio/mpeg` which can be incorrect if the synthesizer returns a non-MP3 format. On the UI side, server-TTS playback creates blob URLs without revoking them, causing leaks during long/active chat sessions.
- src/gateway/tts-http.ts, ui/src/ui/views/chat.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#23778: feat: chat UI facelift — speech, themes, config categories, and polish
by BunsDev · 2026-02-22
77.3%
#7965: feat(tts): add Speechify as TTS provider
by chaerla · 2026-02-03
76.9%
#11965: feat(ui): add speech-to-text dictation to web chat via Deepgram Flux
by billgetman · 2026-02-08
75.3%
#7258: feat(tts): add Inworld AI TTS provider
by willsinghwilson · 2026-02-02
74.5%
#20794: feat(tts): add Fish Audio provider with full docs, tests & gateway ...
by twangodev · 2026-02-19
73.8%
#8922: feat(voice-call): Add ElevenLabs WebSocket streaming TTS
by mikiships · 2026-02-04
73.4%
#4300: Gateway: prevent OpenAI-compatible client crash on SSE termination
by perryraskin · 2026-01-30
73.3%
#7127: fix(webchat): add regenerate flag to prevent context leak on response…
by craihub · 2026-02-02
72.9%
#8317: fix(tts): add dynamic timeout and retry logic for ElevenLabs TTS
by camtang26 · 2026-02-03
72.8%
#9218: Fix Control UI chat resync on gaps and terminal events
by figitaki · 2026-02-05
72.5%