@uniformdev/search
v0.0.11
Published
Uniform Search client with optional React bindings
Readme
@uniformdev/search
A lightweight client for Uniform Search with optional React bindings for building faceted search experiences (filters, sorting, pagination, and URL-synced state).
The core client is framework-agnostic. The React bindings are exposed from a separate @uniformdev/search/react entry point and react is an optional peer dependency, so you only pull in React if you use them.
Getting started with the full UI
Want the complete faceted-search experience (search box, results, facets, sorting, pagination) plus the matching Uniform component definitions scaffolded into an existing Next.js App Router + Uniform project? Run the initializer from your project root:
npm create uniform-search@latest
# or: npx create-uniform-search
# or: pnpm create uniform-searchIt copies the search components + helpers, drops in the Uniform CLI package file, can deploy the Uniform component definitions for you (sync push in additive create mode), and optionally installs the companion Claude Code skill. See create-uniform-search for options. The rest of this README covers using the client library directly.
Installation
npm install @uniformdev/search
# or
pnpm add @uniformdev/search
# or
yarn add @uniformdev/searchTo use the React bindings, make sure React 18+ is installed in your app:
npm install reactQuick start
1. Create a search client
The client posts to ${apiUrl}/api/search and (optionally) attaches an x-api-key header. Configure it with your Uniform Search service URL, API key, and project ID:
import { createSearchClient } from '@uniformdev/search';
const client = createSearchClient({
apiUrl: process.env.NEXT_PUBLIC_UNIFORM_SEARCH_API_URL!, // https://<your-project>.search.uniform.app
apiKey: process.env.NEXT_PUBLIC_UNIFORM_SEARCH_API_KEY,
});
const result = await client.performSearch({
search: 'hello world',
page: 0,
perPage: 10,
});
console.log(result.data.items, result.data.total, result.facets);performSearch never throws — on a network or non-2xx error it logs and returns an empty result shape so your UI can render safely.
2. (React) Wire up the provider
import { SearchProvider, useSearch } from '@uniformdev/search/react';
import { createSearchClient } from '@uniformdev/search';
const client = createSearchClient({
apiUrl: process.env.NEXT_PUBLIC_UNIFORM_SEARCH_API_URL!,
apiKey: process.env.NEXT_PUBLIC_UNIFORM_SEARCH_API_KEY,
});
export function SearchPage() {
return (
<SearchProvider performSearch={client.performSearch}>
<SearchBox />
<Results />
</SearchProvider>
);
}
function SearchBox() {
const { searchBoxValue, setSearchQuery } = useSearch();
return (
<input
value={searchBoxValue}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="Search…"
/>
);
}
function Results() {
const { results, isLoading } = useSearch();
if (isLoading) return <p>Loading…</p>;
return (
<ul>
{results.items.map((item) => (
<li key={item.id}>{String(item.title ?? item.id)}</li>
))}
</ul>
);
}The provider keeps search state (query, page, page size, sort, and selected filters) in sync with the URL query string and debounces text input.
API
Core (@uniformdev/search)
| Export | Description |
|---|---|
| createSearchClient(config) | Creates a SearchClient with a performSearch(params) method. |
| getSearchParamsFromUrl(url) | Parses a URL's query string into a params object. |
| buildOrderByQuery(orderBy) | Builds an orderBy query string (e.g. created_at_DESC). |
| flattenBlockParams(value) | Normalizes Uniform block parameter values into a flat array. |
| Types | SearchParams, SearchClient, CollectionResult, SearchHit, SearchMode, Pagination, Facets, FacetBy, OrderBy, PageSize, and more. |
Semantic search
All optional. Omitting them is the normal case: the endpoint runs meaning-aware search where the project has it enabled and exact matching where it does not, so the same call is correct in both and stays correct when the feature is switched on later.
| Param | Description |
|---|---|
| mode | 'keyword' | 'semantic' | 'hybrid'. Defaults to hybrid where available, keyword otherwise. |
| semanticRatio | Weight of the meaning half in hybrid, 0–1. Defaults to the project's setting. |
| maxDistance | Discard matches beyond this distance. Lower is stricter. |
| similarTo | Documents similar to this id, ignoring search. Costs no embedding call. |
The result reports what actually ran — read it rather than assuming, since a request can be downgraded:
| Field | Description |
|---|---|
| mode | The strategy that ran, which may differ from the one requested. |
| degraded | Meaning-based matching was wanted but unavailable; these are keyword results. Still a normal 200. |
| warnings | Parameters that were adjusted or ignored (e.g. orderBy in hybrid). |
| _vectorDistance / _textMatch / _matchedBy | Per hit: how close, how well it matched lexically, and which half found it. |
const { data, mode, degraded } = await client.performSearch({
search: 'strong bold flavour',
mode: 'hybrid',
});
// "More like this" — no embedding call; the vector is already indexed.
const related = await client.performSearch({ similarTo: docId, perPage: 6 });React (@uniformdev/search/react)
| Export | Description |
|---|---|
| SearchProvider | Context provider that owns search state and runs queries. |
| useSearch() | Hook returning results, facets, loading state, and state setters. Must be used inside a SearchProvider. |
| useSimilarItems(docId, options) | "Related content" — documents nearest the given one. Standalone: takes performSearch directly, no provider needed. Requires semantic search. |
| usePagination, useSearchPagination, DOTS | Pagination helpers. |
| SearchItemUrlResolverProvider, useUrlResolver, createDefaultUrlResolver | Resolve result items to URLs. |
Configuration
createSearchClient accepts:
| Option | Required | Description |
|---|---|---|
| apiUrl | yes | Base URL of your Uniform Search service. /api/search is appended automatically. |
| apiKey | no | Sent as the x-api-key header. |
| projectId | no | Normally not needed: the search API key identifies the project. Pass it only to override the project explicitly. |
License
MIT
