Leadtype
Reference

Search

The API surface for leadtype/search and its subpaths. For tasks, start with Add search, Stream AI answers, and Agent search tools.

Vocabulary

  • Chunk — a heading-aware slice of a page; each is a separate document, so results jump to the right section.
  • Index (search-index.json) — compact term postings + document/chunk refs. Loaded on every search.
  • Content store (search-content.json) — chunk text, separate from the index so search stays cheap and content loads lazily.
  • BM25 — the ranking function. Weights: title 4×, headings 2×, body 1×, code 0.35×.

Build time — leadtype/search/node

NameTypeDefaultDescription
outDirstring-Output root. Reads markdown under `<outDir>/docs/`.
baseUrlstring-Base URL for absolute result links.
mountsDocsPathMount[]-Mounted URL prefixes — match the LLM/Agent Readability generators.
i18nDocsI18nConfig-Localization config; emits per-locale indexes.
localestring-Active locale when i18n is set.
indexOptionsobject-BM25 weight + tokenizer tuning.
transformersDocsTransformer[]-beforeSearchIndex / beforeSearchChunk hooks.

Runtime query — leadtype/search

DocsSearchResult carries title, urlPath, urlWithHash, headingPath, score, and (with content) excerpt. The runtime is edge-safe — no Node APIs.

Content readers

Use readDocsContentFile for a whole page, readDocsContentChunk when a result already named the heading.

Framework hooks

ImportExportReturns
leadtype/search/clientcreateSearchClient(collection, opts?){ search(q), preload() }
leadtype/search/reactuseLeadtypeSearch(collection, opts?){ query, search, results, status, error }
leadtype/next/clientuseLeadtypeSearch(collection, opts?)same (Next App Router)
leadtype/search/vueuseLeadtypeSearch(collection, opts?)refs: { query, results, status, error, search, preload }
leadtype/search/sveltecreateLeadtypeSearch(collection, opts?)stores: { query, results, status, error, search, preload }

status is "idle" | "loading" | "ready" | "error". Options: debounceMs (default 120), plus indexUrl / contentUrl / limit / fetch overrides. Collection "docs" resolves to /docs/search-index.json + /docs/search-content.json.

Answer context & streaming

The system message constrains the model to the retrieved context and [1]-style citations. streamDocsAnswer wraps this per runtime and returns { response: Response, sources: DocsAnswerSource[] } (plain-text stream + separate citations):

ImportModel argumentOther options
leadtype/search/vercelmodel: LanguageModel | stringmaxOutputTokens, timeout, providerOptions, tools
leadtype/search/tanstackadapter: AnyTextAdaptermaxTokens, modelOptions, tools
leadtype/search/cloudflareadapter from createCloudflareDocsAdapter(...)maxTokens

createCloudflareDocsAdapter({ provider, model, options })provider is one of anthropic | gemini | grok | openai | openrouter | workers-ai.

Bash tools — leadtype/search/bash

Read-only virtual /docs with ls, cat, find, grep, rg. No network, no execution, no writes.

Endpoint guards — leadtype/search

HelperPurpose
validateDocsQuery(input, { maxChars, fieldName? })Trim and cap query text.
readJsonWithLimit(request, { maxBytes })Reject oversized JSON bodies before parse.
getClientIdentifier(request, { fallback? })Read proxy IP headers for a limiter key.
createMemoryRateLimiter({ limit, windowMs })In-memory RateLimiter (demos).

Adapt RateLimiter to a shared store (Redis, Vercel KV, Cloudflare KV, Durable Objects) in production. Defaults live in docsSearchDefaults:

KeyDefault
maxQueryChars400
askMaxQueryChars600
maxContextChars12000
maxSources6
searchLimit8
maxBodyBytes16 KB

When to add embeddings

Start with the local index — static, cheap, edge-safe, and precise for API names, config keys, error messages, and paths. Add embeddings only when users search with vocabulary the docs don't use, or the corpus grows past tens of thousands of chunks. Even then, keep the lexical index for exact matches and layer embeddings on top.