Search

Oxidoc ships a production-grade search engine that runs entirely in the browser via WebAssembly. No server, no external service, no API keys — just build your site and search works.

Overview

FeatureStatusDetails
Lexical (BM25)Enabled by defaultZero config, always works
Semantic embeddingsOpt-insemantic = true in config
Hybrid ranking (RRF)AutomaticWhen semantic is enabled, fuses both result sets
Fuzzy matchingBuilt-inTolerates typos based on term length
Section-level resultsBuilt-inLinks to the exact heading, not just the page
Lazy chunk loadingBuilt-inOnly fetches index data matching query terms
Custom modelsSupportedProvide your own GGUF sentence embedding model
External providersSupportedAlgolia, Typesense, Meilisearch, or custom JS

How It Works

graph TD
    B[oxidoc build] --> L[BM25 Index]
    B --> S[Embedding Vectors]
    B --> M[Model Copy]
    L --> C[Chunked by term prefix]
    C --> W[Browser / Wasm]
    S --> W
    M --> W
    W --> Q[User Query]
    Q --> LR[Lexical Results]
    Q --> SR[Semantic Results]
    LR --> RRF[Reciprocal Rank Fusion]
    SR --> RRF
    RRF --> R[Ranked Results]

At build time, Oxidoc generates a search index from all your pages. The index is split into small chunks so the browser only downloads what's needed for each query. When semantic search is enabled, pre-computed embedding vectors and the model file are also included in the output.

Quick Start

Search works out of the box. To enable semantic search:

oxidoc.tomltoml
[search]
semantic = true

That's it. See the subpages for deep dives into each feature.

Output Files

When using the built-in provider, oxidoc build generates these search files in dist/:

FilePurposeLoaded
search-meta.binDocument metadata + chunk manifestAlways (on page load)
search-chunk-{id}.binLexical postings for term prefixesOn demand (per query)
search-vectors.jsonPre-computed page embeddingsOnly if semantic enabled
search-model.ggufEmbedding model for query-time inferenceOnly if semantic enabled