Getting Started
Install SearchFn, index documents, and run your first search query in minutes.
Packages
SearchFn is split into focused packages. Install only what you need:
| Package | Purpose |
|---|---|
@searchfn/core | Built-in search engine (text pipeline, BM25 scoring, inverted index, fuzzy matching) |
@searchfn/adapters | Adapter implementations — Memory and IndexedDB (built-in engine), Postgres, Meilisearch, Elasticsearch/OpenSearch (external backends) |
@searchfn/client | Client API for app code that calls search directly (browser or Node) |
@searchfn/server | HTTP server exposing /searchfn/* endpoints with authorization and logging |
@searchfn/datafn-provider | DataFn integration — maps any adapter into a DataFn SearchProvider |
Installation
For client-side or in-process search (uses the built-in search engine):
npm install @searchfn/client @searchfn/adaptersFor server-side HTTP search API:
npm install @searchfn/server @searchfn/adaptersQuick Start
The quickstart uses MemoryAdapter, which runs SearchFn's built-in search engine in-process. No external services required — this is the same engine that powers production in-process and offline-first search.
1. Create a Client
import { createSearchClient } from "@searchfn/client";
import { MemoryAdapter } from "@searchfn/adapters";
const client = createSearchClient({
adapter: new MemoryAdapter(),
defaults: {
limit: 20,
limitPerResource: 10,
fuzzy: true,
},
});2. Initialize Resources
Before indexing, declare which resources exist and which fields are searchable:
await client.initialize?.({
resources: [
{ name: "tasks", searchFields: ["title", "description"] },
{ name: "notes", searchFields: ["content"] },
],
});3. Index Documents
await client.index({
resource: "tasks",
documents: [
{ id: "t-1", fields: { title: "Ship docs", description: "Write getting started guide" } },
{ id: "t-2", fields: { title: "Fix bug", description: "Handle retry logic" } },
{ id: "t-3", fields: { title: "Plan launch", description: "Coordinate docs and release" } },
],
});4. Search
const ids = await client.search({
resource: "tasks",
query: "docs",
limit: 5,
});
console.log(ids); // ["t-1", "t-3"]5. Search Across Resources
const results = await client.searchAll({
query: "docs",
resources: ["tasks", "notes"],
limitPerResource: 5,
});
// [{ resource: "tasks", id: "t-1", score: 1.2 }, ...]Server Quick Start
The server wraps any adapter behind HTTP endpoints with built-in validation, authorization, and structured logging.
import { createSearchFnServer } from "@searchfn/server";
import { MemoryAdapter } from "@searchfn/adapters";
const server = await createSearchFnServer({
adapter: new MemoryAdapter(),
basePath: "/searchfn",
});
// Mount server.router with your @superfunctions/http adapter (Express, Fastify, Hono, etc.)The server exposes these endpoints under the configured basePath:
| Endpoint | Method | Description |
|---|---|---|
/searchfn/status | GET | Health check and adapter info |
/searchfn/index | POST | Index documents into a resource |
/searchfn/search | POST | Search a single resource |
/searchfn/search-all | POST | Search across multiple resources |
/searchfn/remove | POST | Remove documents by ID |
/searchfn/clear | POST | Clear all documents in a resource |
Convenience Constructors
For common setups, use the built-in shorthand constructors:
import { createMemorySearchClient, createIndexedDbSearchClient } from "@searchfn/client";
const memoryClient = createMemorySearchClient({
defaults: { limit: 20, fuzzy: true },
});
const browserClient = createIndexedDbSearchClient({
adapterConfig: { dbName: "my-app-search" },
defaults: { limit: 20, fuzzy: true },
});Next Steps
- Architecture — search engine internals and adapter contract.
- Adapters — choose the right adapter for your use case.
- Client API — full method reference.
- Server API — endpoint details and authorization.
- Operations — deployment, limits, and production setup.