@dooo/voice-product-search
v0.1.3
Published
Fast multilingual product autocomplete and voice command parsing for TypeScript, with React UI
Maintainers
Readme
Voice Product Search
Voice Product Search
─────────────────────
Fast multilingual product autocomplete
and Gemini-inspired voice UI for TypeScript.Copyright © 2026 dooo.vn · MIT License
Package:@dooo/voice-product-search

High-performance indexed product search + multilingual voice parsing + polished React voice UI.
Features
- Indexed autocomplete for 10k–100k+ products (not full-scan fuzzy)
- Vietnamese + English locales (extensible to ja/ko/zh)
- Voice command parsing with quantity extraction
- Zero runtime dependencies in core
- Optional React UI: floating trigger, listening sheet, orb, waveform, suggestions
- Pluggable
SpeechProvider(Web Speech / mock / custom) - SSR-safe core; React entry marked
"use client"for Next.js
Installation
npm install @dooo/voice-product-searchReact peer deps (only if using UI):
npm install react react-domQuick Start (core)
import {
createProductSearch,
createVoiceProductParser,
} from "@dooo/voice-product-search";
const products = [
{ id: "omo-36", name: "Nước giặt Omo 3.6kg", aliases: ["omo", "omo 3.6"] },
];
const search = createProductSearch({ products });
search.search("omo 3");
const parser = createVoiceProductParser({ products, locale: "vi-VN" });
parser.parse("cho tôi 3 omo");
const en = createVoiceProductParser({ products, locale: "en-US" });
en.parse("give me 3 omo");React Installation
Peer dependencies for the React UI: react, react-dom, lucide-react.
import { VoiceProductSearch } from "@dooo/voice-product-search/react";
import "@dooo/voice-product-search/react/voice.css";
function App() {
return (
<VoiceProductSearch
products={products}
locale="vi-VN"
theme="system"
confidenceThreshold={0.92}
onApply={(commands) => {
console.log(commands);
}}
/>
);
}In Next.js App Router, use this from a Client Component ("use client").
The React layer uses shadcn/ui (Radix + Tailwind semantic tokens). Core stays framework-independent.
Assistant wake words
Open the voice sheet by saying a phrase (defaults: hey dooo, hey doo, dooo, hey), or pass your own:
<VoiceProductSearch
products={products}
locale="vi-VN"
assistant={{
enabled: true,
wakeWords: ["hey dooo", "dooo", "trợ lý"],
onWake: (matched) => console.log("wake", matched),
}}
onApply={(commands) => console.log(commands)}
/>Requires microphone + Chrome/Edge (HTTPS or localhost). The mic button still works.
Floating Voice Button
Default fixed trigger at bottom-right (safe-area aware). Positions: bottom-right | bottom-left | top-right | top-left. Tooltip text comes from i18n.
Voice Sheet
Clicking the trigger opens a premium bottom sheet (max ~640px on desktop) with orb, waveform, live transcript, Command-based suggestions, and confirm/apply.
Multilingual Usage
<VoiceProductSearch locale="en-US" />
<VoiceProductSearch locale="ja-JP" />UI strings are localized; pass translations to override.
Custom Speech Provider
import { createWebSpeechProvider, createMockSpeechProvider } from "@dooo/voice-product-search";
const speech = createWebSpeechProvider({ locale: "vi-VN" });
// or demo without mic:
const mock = createMockSpeechProvider();<VoiceProductSearch speechProvider={speech} />Package exports
| Import | Purpose |
|--------|---------|
| @dooo/voice-product-search | Core search + voice parser + locales |
| @dooo/voice-product-search/react | React UI components + hooks |
| @dooo/voice-product-search/react/voice.css | Styles |
| @dooo/voice-product-search/web-speech | Web Speech adapter |
Architecture
Core (0 deps) → locale → speech provider → React UISearch remains indexed: token / prefix / alias → candidate set → fuzzy → top-K → confidence.
Demo
Live demo (HTTPS): https://vietnamese-voice-search.vercel.app
Use Chrome/Edge on the live URL so Web Speech + microphone work (secure context).
npm run demoPreview GIF: docs/media/demo.gif
Regenerate the README demo GIF (requires the demo server + a Chromium browser):
npm run demo:gifBenchmarks
npm run benchSee benchmarks/results/ for measured numbers.
