Search & AI Answers

Add search

Leadtype search is static by default. Build time produces two JSON files; runtime code loads them and queries them locally — no database, edge-safe.

Generate the files

leadtype generate writes the search files in site mode:

npx leadtype generate --src . --out public --base-url https://example.com

If you run the pipeline from scripts, call the generator after conversion:

import { generateDocsSearchFiles } from "leadtype/search/node";

await generateDocsSearchFiles({
  outDir: "public",
  baseUrl: "https://example.com",
});

This writes:

public/docs/search-index.json     # compact ranking data — load on every search
public/docs/search-content.json   # chunk text — load lazily for excerpts/answers

Query at runtime

For server routes or any code that already has the JSON, query directly with searchDocs:

import {
  searchDocs,
  type DocsSearchContentStore,
  type DocsSearchIndex,
} from "leadtype/search";
import contentJson from "./search-content";
import indexJson from "./search-index";

const index = indexJson as DocsSearchIndex;
const content = contentJson as DocsSearchContentStore;

const results = searchDocs(index, "run lint", { content });

Results carry page URLs, heading paths, hash URLs, and snippets — render them in your own UI. See the reference for the full result shape and options.

Wire a search UI

For a client search box, use the framework hook instead of fetching and querying by hand. Each loads /docs/search-index.json + /docs/search-content.json (by collection name), debounces input, and manages loading state.

import { useLeadtypeSearch } from "leadtype/search/react";

export function DocsSearch() {
  const { search, results, status } = useLeadtypeSearch("docs");
  return (
    <div>
      <input
        aria-label="Search docs"
        onChange={(event) => search(event.target.value)}
        placeholder="Search docs"
      />
      <span>{status}</span>
      <ul>
        {results.map((result) => (
          <li key={result.id}>
            <a href={result.urlWithHash}>{result.title}</a>
          </li>
        ))}
      </ul>
    </div>
  );
}

Next App Router apps can import the same hook from leadtype/next/client.

The collection name ("docs") maps to /docs/search-index.json and /docs/search-content.json. Override the URLs via client options when your artifacts live elsewhere.

Add vocabulary aliases

Search already does stemming, prefix matches, typo-tolerant fallbacks, and a small built-in synonym map. Add product-specific synonyms only when users search with words your docs don't use:

const results = searchDocs(index, "starter", {
  content,
  synonyms: { starter: ["quickstart", "getting started"] },
});

Next steps

  • Stream AI answers — source-grounded answers over the same index, across Vercel AI SDK, TanStack AI, and Cloudflare Workers AI, with a hardened endpoint.
  • Agent search tools — let an agent explore docs with ls/cat/grep instead of pre-selected chunks.

Verify

  • public/docs/search-index.json and search-content.json exist and are non-empty.
  • Searching for an exact API name returns the expected reference page.
  • Searching for a guide phrase returns a result with a section hash.