# Voice archetype gallery Code: `core/voice_archetypes.py` (catalog + filter), `routes/archetypes.py`, UI `static/js/voice-archetypes.js` (core module) + card in `static/sections/s-design.html`. **Catalog:** 40 entries authored here (no third-party data or code). Fields: `id`, `name_de`, `name_en`, `instruct` (free-text Qwen3 VoiceDesign description; German prompts transliterated to ASCII like the existing design presets), `category` (7 fixed), `language` (German/English), `facets` {gender, age, pitch, accent, tone} from the `DESIGN_CHIPS` vocabulary, `sample_script_de/en` (per category). Validated at import: unknown facet, category, language or duplicate/odd id raises ValueError (unit-tested). **API** - `GET /api/archetypes?gender&age&pitch&accent&language&category&q&offset&limit` -> `{total, items, categories, cached}`; limit capped at 100, q at 100 chars. - `POST /api/archetypes/{id}/preview` -> WAV. Cache `/archetype_previews/.wav`; engine is the configured voice-design model, seed fixed to 42 (injected as extra param for this call only). Rendering goes through `_voice_design_request_audio` inside the shared bounded TTS queue, 240 s timeout, per-key lock, size cap 8 MB, blank/too-short audio rejected (502), atomic write. Cache is naturally bounded by the catalog size. - `POST /api/archetypes/{id}/use` -> saves voice `archetype_` (normalized WAV from the cached preview, reference text = sample script, meta `origin: designed`, `voice_design_prompt`). Idempotent: an existing voice returns `created: false`. **Provenance choice:** `core/provenance.BASES` has no "synthetic" value, so basis is `unknown` (closest; nothing to consent to), `source` `archetype/` (a `:` would be parsed as a URL scheme and rejected), `note` "synthetic designed voice". **UI:** the card is a collapsed `
`; nothing is fetched or rendered until opened (DOM budget). 24 cards per page ("Load more"), favourites in localStorage (guarded), DE translations in `i18n.js`. **Pre-render:** `scripts/render_archetype_previews.py` calls the preview endpoint for every entry (sequential, idempotent). No API key needed: the API-key gate accepts same-origin requests, so the script sends `Origin: `; only local/LAN bases accepted. Not done: per-archetype audio shipped in the repo, user-defined archetypes, community import.