/packages/search-worker/CLAUDE.md
CLAUDE.md at /packages/search-worker/CLAUDE.md
Path: packages/
search-worker
Cloudflare Worker sub-package providing a server-side search API. Additional option for large doc bases — the primary search remains the in-browser MiniSearch island (pages/), which loads the same search-index.json emitted by the @takazudo/ zfb integration.
Tech Stack
Cloudflare Workers — runtime
Cloudflare KV — rate limiting storage
MiniSearch — full-text search (same engine as client-side)
TypeScript — strict mode,
@cloudflare/workers-types
Commands
pnpm dev— local dev server (requireswrangler.tomlwith correctDOCS_SITE_URL)pnpm run deploy— deploy to Cloudflare Workers via Wranglerpnpm typecheck— TypeScript type checking
Architecture
src/
├── index. ts # Worker entry — routing, validation, CORS
├── cors. ts # CORS headers (exposes Retry- After)
├── rate- limit. ts # Per- IP rate limiting via KV (60/ min, 1000/ day)
├── search. ts # MiniSearch index loader + search logic
└── types. ts # Env, request/ response typesRequest Flow
CORS preflight →
cors.tsMethod + path check → 405/404
Hash client IP (SHA-256 via Web Crypto)
JSON parse + query validation → 400 (query required, max 500 chars)
Rate limit check → 429 with
Retry-AfterFetch
search-index.jsonfrom docs site (cached with 5-minute TTL) →search.tsMiniSearch search with prefix, fuzzy, and boost → results
Key Design Decisions
Additive, not replacement — client-side MiniSearch handles most users. Worker is for API consumers and huge doc bases
Index from deployed site — fetches
${DOCS_, same data as client-sideSITE_ URL}/ search- index. json 5-minute cache TTL — balances freshness with performance. Isolate recycle also clears cache
Same search config as client —
prefix: true, fuzzy: 0.2, boost: { title: 3, description: 2 }
Configuration
DOCS_SITE_URL— base URL of the deployed docs site (set inwrangler.toml[vars])RATE_LIMIT— KV namespace for rate limiting (create viawrangler kv namespace create)RATE_LIMIT_PER_MINUTE/RATE_LIMIT_PER_DAY— configurable inwrangler.toml
Conventions
All responses include CORS headers (including error responses)
Error responses use
{ error: string }formatRate limit uses
cf-connecting-ipfor client IPQuery length capped at 500 characters
Default result limit: 20, max: 100