* feat(gallery): lucide icons + country flags + card redesign (replace emoji)
- backend archetypes emit lucide-react icon *names* (cross-platform; emoji
render inconsistently across OSes) for use-cases and the 24 featured voices.
- new frontend/src/utils/archetypeIcons.jsx: name→lucide map, accent→country
flag (country-flag-icons, tree-shaken to ~11), per-category color scale,
color-coded avatar tile, and a CSS-animated now-playing equalizer
(prefers-reduced-motion aware).
- card redesign: real elevated surfaces (cards were invisible on the dark bg),
avatar + name + facet sub-line, accent/flag chips, and a footer with
Preview / category-colored "Use voice" / Open-in-Designer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(marketplace): community voice gallery via omnivoice-gallery submodule
Offloads curated + community gallery content to the standalone
debpalash/omnivoice-gallery repo — added here as a submodule for authoring,
loaded at runtime via the jsDelivr CDN so the binary stays small.
Content repo (seeded + pushed separately): manifest.json (24-voice starter
pack generated from the featured archetypes), a JSON schema, CONTRIBUTING,
and GitHub submission templates carrying consent / no-impersonation guardrails.
Backend (api/routers/community.py): configurable sources (env var > file >
default), CDN fetch with offline disk cache, strict validation (invalid
presets and non-allow-listed audio URLs are dropped, so a bad community entry
can neither crash synthesis nor fetch from an arbitrary host), filtering, the
prefilled submit URL, and "use" (preset → archetype render path; voice →
sha256-verified download). 11 tests.
Frontend: a third gallery zone, "Community", reusing the redesigned card, plus
"Submit a preset / voice" buttons opening the prefilled GitHub forms.
Local-first preserved: network only on open/refresh; everything cached; the
built-in generated archetypes need no network, so the gallery is never empty.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(marketplace): address review feedback on the community gallery
- community_use: run the blocking manifest read + voice download in a thread
(asyncio.to_thread) so they don't stall the event loop (greptile P2).
- community_submit_url: validate the `source` override against an owner/repo
pattern, falling back to the configured default (greptile P1 hardening).
- rename the `type` query param to `item_type` (alias="type") so it no longer
shadows the Python builtin (coderabbit).
- frontend submit buttons use the canonical openExternal() (Tauri-aware) instead
of window.open, which doesn't open the system browser in the desktop app.
- lowercase the `currentcolor` CSS keyword (stylelint).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(marketplace): rename useCommunityItem -> addCommunityItem (not a hook)
Avoids the use-prefix on a plain API function (rules-of-hooks smell).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>