ai-smart-search
v0.1.0
Published
AI-powered React UI components — SmartSearch with Gemini integration
Maintainers
Readme
ai-smart-search
AI-powered search component for React. Type a query and get intelligent suggestions, auto-corrections, filter extraction, and related searches — powered by Google Gemini.
Zero CSS dependencies. Works in any React project (Next.js, Vite, Remix, CRA) without Tailwind or any external stylesheet.
Installation
npm install ai-smart-searchInstall peer dependencies:
npm install lucide-react framer-motionQuick Start
1. Add the API route (Next.js App Router)
// app/api/suggest/route.ts
import { createNextSuggestRoute } from "ai-smart-search/server";
export const POST = createNextSuggestRoute({
rateLimit: { windowMs: 60_000, max: 30 },
});Set your Gemini API key in .env.local:
GEMINI_API_KEY=your_gemini_api_key_here2. Use the component
import { SmartSearch } from "ai-smart-search";
export default function SearchPage() {
return (
<SmartSearch
placeholder="Search anything..."
onSearch={(query, metadata) => {
console.log("Search:", query);
console.log("AI analysis:", metadata);
}}
/>
);
}That's it. The component renders with a clean default theme and all styles are self-contained.
Theme Customization
Preset Themes
6 built-in themes: default, dark, rose, amber, ocean, zinc
import { SmartSearch, SmartUIProvider } from "ai-smart-search";
export default function App() {
return (
<SmartUIProvider config={{ preset: "dark" }}>
<SmartSearch onSearch={(q) => console.log(q)} />
</SmartUIProvider>
);
}Custom Theme
Override any token:
<SmartUIProvider
config={{
preset: "dark",
theme: {
primary: "#e11d48",
radius: "8px",
fontFamily: "'Inter', sans-serif",
},
}}
>
<SmartSearch />
</SmartUIProvider>Match Your Project's Theme (CSS Variables)
Pass your existing CSS variables directly:
<SmartUIProvider
config={{
theme: {
primary: "var(--color-primary)",
background: "var(--background)",
inputText: "var(--foreground)",
fontFamily: "var(--font-sans)",
},
}}
>
<SmartSearch />
</SmartUIProvider>shadcn/ui Integration
<SmartUIProvider
config={{
theme: {
primary: "hsl(var(--primary))",
primaryForeground: "hsl(var(--primary-foreground))",
background: "hsl(var(--background))",
border: "hsl(var(--border))",
inputText: "hsl(var(--foreground))",
muted: "hsl(var(--muted-foreground))",
radius: "var(--radius)",
},
}}
>
<SmartSearch />
</SmartUIProvider>All Theme Tokens
| Token | Default | Description |
|---|---|---|
| primary | #6366f1 | Brand color (focus ring, active states) |
| primaryForeground | #ffffff | Text on primary background |
| background | #ffffff | Input background |
| border | #e2e8f0 | Input border color |
| inputText | #1e293b | Typed text color |
| placeholderText | #94a3b8 | Placeholder text |
| ghostText | rgba(148,163,184,0.45) | Ghost suggestion text |
| muted | #94a3b8 | Secondary text, icons |
| error | #f87171 | Error state color |
| success | #10b981 | Success / complex-query badge |
| chipBg | rgba(99,102,241,0.10) | Filter chip background |
| chipText | #6366f1 | Filter chip text |
| chipBorder | rgba(99,102,241,0.20) | Filter chip border |
| pillBg | #f1f5f9 | Related search pill background |
| pillText | #475569 | Related search pill text |
| radius | 16px | Input border radius |
| shadow | 0 1px 3px rgba(0,0,0,0.06) | Input box shadow |
| ringColor | rgba(99,102,241,0.15) | Focus ring color |
| ringWidth | 4px | Focus ring width |
| fontSize | 1.125rem | Input font size |
| fontFamily | inherit | Font family |
SmartSearch Props
| Prop | Type | Default | Description |
|---|---|---|---|
| placeholder | string | "Search anything with AI..." | Input placeholder |
| className | string | "" | Extra class on root element |
| inputClassName | string | "" | Extra class on the input |
| panelClassName | string | "" | Extra class on the panel |
| onSearch | (query, metadata?) => void | — | Fires on Enter or Tab-accept |
| onFiltersChange | (filters) => void | — | Fires when AI extracts filters |
| apiEndpoint | string | "/api/suggest" | API route URL |
| debounceMs | number | 300 | Debounce delay in ms |
| minQueryLength | number | 2 | Min characters before AI fires |
Server Handler
Next.js App Router
// app/api/suggest/route.ts
import { createNextSuggestRoute } from "ai-smart-search/server";
export const POST = createNextSuggestRoute({
apiKey: process.env.GEMINI_API_KEY, // optional, reads env by default
model: "gemini-2.0-flash", // optional
rateLimit: { windowMs: 60_000, max: 30 }, // optional
});Framework-Agnostic (Express, Fastify, etc.)
import { createSmartSearchHandler } from "ai-smart-search/server";
const handler = createSmartSearchHandler({
apiKey: process.env.GEMINI_API_KEY,
rateLimit: { windowMs: 60_000, max: 30 },
});
// Express example
app.post("/api/suggest", async (req, res) => {
const result = await handler.handle(req.body, req.ip);
res.json(result);
});Plugins
Extend behavior with plugins:
<SmartUIProvider
config={{
plugins: [
{
name: "analytics",
onSearch: (query, metadata) => {
analytics.track("search", { query, intent: metadata?.intent });
},
onFiltersChange: (filters) => {
console.log("Active filters:", filters);
},
transformSuggestions: (suggestions) => {
return suggestions.map((s) => s.toLowerCase());
},
},
],
}}
>
<SmartSearch />
</SmartUIProvider>Plugin Hooks
| Hook | Signature | Description |
|---|---|---|
| onQueryChange | (query: string) => void | Fires on every keystroke |
| onFiltersChange | (filters: Record<string, string>) => void | AI extracted filters |
| onSearch | (query, metadata) => void | User pressed Enter |
| transformSuggestions | (suggestions: string[]) => string[] | Modify suggestions |
| renderExtension | (query: string) => ReactNode | Render custom UI below panel |
Auto Dark Mode
"use client";
import { useEffect, useState } from "react";
import { SmartSearch, SmartUIProvider } from "ai-smart-search";
export function Search() {
const [dark, setDark] = useState(false);
useEffect(() => {
const mq = window.matchMedia("(prefers-color-scheme: dark)");
setDark(mq.matches);
mq.addEventListener("change", (e) => setDark(e.matches));
}, []);
return (
<SmartUIProvider config={{ preset: dark ? "dark" : "default" }}>
<SmartSearch onSearch={(q) => console.log(q)} />
</SmartUIProvider>
);
}TypeScript
All types are exported:
import type {
SmartUITheme,
SmartUIConfig,
SmartUIPlugin,
SmartSearchAnalysis,
SuggestRequest,
SuggestResponse,
AISuggestionMode,
} from "ai-smart-search";License
MIT
