# SkillPatch skill: extension-tts-proxy-architect

Designs secure proxy architectures for browser extensions to safely consume AI Text-to-Speech APIs without leaking keys.

You (the agent) were given this URL and asked to use this skill. This is a **public** skill — no SkillPatch account, API key, or prior setup is required. Two ways to use it:

**1. Use it right now** — the skill's complete file tree (SKILL.md + all reference files) is inlined below; read `SKILL.md` first, then follow it, consulting the other files as it directs.

**2. Install the exact package onto disk** (recommended if you can run a shell — this reproduces the skill byte-for-byte, including any binary assets that can't be inlined):

```bash
mkdir -p .claude/skills/extension-tts-proxy-architect
curl -sSL https://skillpatch.dev/install_skill/extension-tts-proxy-architect | tar -xz -C .claude/skills/
```

(`.claude/skills/` is Claude Code's convention; use whatever directory your agent loads skills from.)


---

## Skill files (1)

- `SKILL.md`


### `SKILL.md`

```markdown
---
name: extension-tts-proxy-architect
summary: Designs secure proxy architectures for browser extensions to safely consume AI Text-to-Speech APIs without leaking keys.
tags: ["browser-extension", "architecture", "tts", "proxy"]
---

# Extension TTS Proxy Architect

Use this skill when a user wants to integrate external Text-to-Speech (TTS) or other authenticated AI APIs into a browser extension.

## Context
Browser extensions execute entirely on the client-side. Embedding API keys (like OpenAI, Sarvam, ElevenLabs) inside `background.js` or `content.js` exposes those keys to anyone who inspects the extension source code.

## The Solution Workflow
When asked to add an AI/TTS feature to a browser extension, do not put the fetch call in the extension code. Instead, implement the following Two-Tier Architecture:

### Tier 1: The Local Node.js Proxy Server
1. Create a lightweight Express.js server (`tts-server.js`).
2. Implement CORS (`app.use(cors())`) and JSON body parsing.
3. Load API keys via `.env` (`process.env.API_KEY`).
4. Create a single `POST` endpoint (e.g., `/tts`) that accepts the text and language.
5. The server makes the secure call to the external AI provider.
6. The server receives the raw audio buffer or base64 JSON, handles any provider-specific mapping (e.g., translating `es-ES` to `es`), and returns a standardized JSON object to the extension containing the base64 audio string.

### Tier 2: The Extension Client (`manifest.json` & `content.js`)
1. **Manifest Configuration:** Ensure `host_permissions` explicitly includes the local proxy server (e.g., `"http://localhost:3001/*"`) alongside any production domains.
2. **Background Script Routing:** Have `content.js` use `chrome.runtime.sendMessage` to pass the selected text to `background.js`.
3. **Secure Fetching:** The `background.js` executes the `fetch` request to the local proxy server.
4. **Playback:** Pass the returned base64 string back to `content.js`, decode it safely using `atob()`, convert it to a `Blob`, and play it via an `Audio` object.

## Fallback Routing Strategy
For TTS systems that only support specific regional languages (e.g., Indic languages), implement a fallback mechanism:
1. The proxy server should validate the requested language against an allowed array.
2. If the language is unsupported by the AI provider, the server should instantly return a JSON payload with a special flag: `{ useBrowserTTS: true }`.
3. The `content.js` script must intercept this flag *before* attempting to decode audio, falling back immediately to `window.speechSynthesis`.

## Common Pitfalls to Avoid
- **Hardcoding `-IN` or locale suffixes:** AI providers frequently change their expected language code formats (e.g., `hi-IN` vs `hi`). Always extract the base language using `lang.split('-')[0]` if the API rejects strict locales.
- **Audio Decoding Crashes:** Always validate that `response.audio` actually exists before running `atob(response.audio)`. Attempting to decode `undefined` will crash the extension with a `DOMException`.

```
