Skip to content

Search#

View Markdown

Full-text search is enabled by default. The index is built during the build — in Rust, with BM25 scoring — and shipped as a static JSON file, so search works on any static host with no server component.

Try it on this site: press / or ⌘K, or click the search box in the header.

The search dialog on this site

Configuration#

import { oxContent } from "@ox-content/vite-plugin";

export default {
  plugins: [
    oxContent({
      search: {
        limit: 8,
        hotkey: "/",
        placeholder: "Search documentation...",
      },
    }),
  ],
};
Option Default Purpose
enabled true Set search: false to disable entirely.
limit 10 Maximum results returned by the client.
prefix true Prefix-match the last query token (typeahead).
placeholder "Search documentation..." Input placeholder in the default theme.
hotkey "/" Focus hotkey; "" opts out of registration.

The index is written to search-index.json next to the generated pages and fetched lazily the first time a reader searches. During dev it is served from memory and rebuilt as pages change.

Client API#

The default SSG theme wires the search UI for you. For custom UIs, the same index is available to any client code through a virtual module:

import { search, searchOptions } from "virtual:ox-content/search";

const results = await search("code annotations", { limit: 5 });

for (const result of results) {
  // { id, title, url, score, matches, snippet }
  console.log(result.title, result.url, result.snippet);
}
  • search(query, options?) loads the index on first call, then scores with BM25. options.limit and options.prefix override the configured defaults per call.
  • searchOptions exposes the resolved { enabled, limit, prefix, placeholder, hotkey } so a custom UI can honor the site configuration.
  • Scoped queries like @api transform restrict results to a section of the site.

When search is disabled, the virtual module still resolves — search() returns an empty array and searchOptions.enabled is false — so custom UIs do not need conditional imports.

Last updated: