Add search in five minutes or press ⌘K to watch it search these docs.

API

SearchOverlay component

SearchOverlay.astro renders the ⌘K command palette. Add it once in a global layout. It’s a <dialog> that opens over the page; it doesn’t affect layout until opened.

---
import SearchOverlay from "@hevmind/ask/components/SearchOverlay.astro";
---
<SearchOverlay />

Props

PropTypeDefaultDescription
endpointstring'/api/ask'Endpoint the overlay posts queries to. Must match the integration’s endpoint option.
placeholderstring'Search the docs…'Placeholder text for the input.
debouncenumber500Milliseconds after typing stops before a keyword query is sent.
<SearchOverlay
  endpoint="/api/ask"
  placeholder="Search hev ask…"
  debounce={400}
/>

Opening the overlay

Two ways, both built in:

  • ⌘K / Ctrl-K is bound automatically once the component is on the page.
  • Any element with data-hev-ask-open opens it on click — wire up as many triggers as you like (header button, sidebar, inline links).
<button type="button" data-hev-ask-open>
  Search <kbd>⌘K</kbd>
</button>

<a href="#" data-hev-ask-open>Search the docs</a>

Keyboard model

The overlay is ask-first: the number of words you’ve typed decides the path.

  • Open (with AI on) → a few suggested questions appear. Click one, or press Tab to drop the first into the input, to ask it.
  • Type one word → debounced keyword search runs; the first result is auto-active. This is the instant, keyless lookup path.
  • Type a space (a second word) → keyword type-ahead stops and the overlay switches to ask mode: the results area shows an Ask AI affordance and Enter sends the question to the agentic loop.
  • Enter → in ask mode, runs the agentic loop. In keyword mode, opens the active result. (If you moved the selection with / on a single-word query, Enter opens that result instead of asking.)
  • / → move the active keyword result. Esc → close.

So type a question → Enter asks AI, and type one word → Enter (or ↓↓ → Enter) opens a keyword hit. The footer hint reflects the current mode.

Suggested questions

When AI is on, the overlay fetches a short list of suggested questions from the endpoint (GET /api/ask) the first time it opens and shows them in the empty state. They come from the digest’s suggestions, baked in at build time, so there’s no model call to render them — and if the digest has none, the overlay simply shows nothing extra. Clicking a suggestion fills the input and asks it immediately.

The mode toggle

The overlay persists an “AI on Enter” preference in localStorage under the key hev-ask:mode (agentic or keyword). Readers who flip it to keyword-only never trigger a model call: a space just searches for a phrase, and no suggested questions are shown. The choice survives reloads.

Each keyword result row renders the document title, an optional heading breadcrumb (Concepts › The agentic loop), and a one-line snippet. The row’s link is the chunk’s url, which already carries the #anchor — so clicking a result lands on the exact heading.

The streamed answer

Pressing Enter (with a key configured) replaces the keyword rows with an answer panel. The sub-queries the model runs appear live as a faint searched: … line, then the grounded answer streams in token-by-token with a blinking caret until it completes. Inline deep links in the prose are styled in the accent color and point at the exact /docs/page#anchor; hovering shows the section breadcrumb. A Sources chip row beneath the answer lists every section it drew from.

Links are validated against the source set the endpoint streamed: any link the model emits to a URL outside that set is rendered as plain text, so a hallucinated anchor can never become a clickable dead link.

Theming

The overlay’s markup uses the as- class prefix and reads your page’s CSS custom properties. Define these on :root (this site’s values shown) and the overlay inherits your palette:

:root {
  --paper: #111111;       /* overlay background */
  --ink: #fafaf5;         /* primary text */
  --muted: #6b6b66;       /* secondary text */
  --signal: #e25822;      /* accent / active state */
}

Because the component ships scoped styles keyed to these variables, matching your site’s look is usually just defining the tokens — no overlay CSS to override.

The overlay on other frameworks

SearchOverlay.astro is the Astro distribution of the overlay. The same palette ships as a prebuilt web component, @hevmind/ask/overlay, that any site loads with one script tag from npm or a CDN. It reads a bundled copy of the digest in the browser, so keyword search runs fully static, and it sends agentic questions to whatever endpoint you point it at.

<script
  type="module"
  src="https://cdn.jsdelivr.net/npm/@hevmind/ask/overlay.js"
  data-hev-ask-digest="/hev-ask/"
  data-hev-ask-endpoint="https://docs-ask.example.workers.dev/api/ask"
></script>

<button data-hev-ask-open>Search <kbd>⌘K</kbd></button>
  • data-hev-ask-digest — the URL prefix where ask digest bundle wrote the static assets. This is all keyword search needs.
  • data-hev-ask-endpoint — optional. Omit it and the overlay is keyword-only; set it and pressing Enter runs the agentic loop. The key lives on the endpoint and never reaches the browser.

The drop-in overlay reads the same CSS custom properties as the Astro component, so the theming section applies unchanged. The opener attribute and keyboard model are also identical.

Bundling the static assets

ask digest bundle emits the browser payload (the keyword index, glossary, suggestions, and title-tree) into a directory your site serves. Run it in your build, like the step that renders your HTML. The output is served, not committed: gitignore it, and keep the committed .hev-ask/ tree as the reviewable source of truth. Regenerating the assets every build means they can’t drift from what you deploy.

The hostable endpoint

For agentic answers without Astro, deploy the bounded answer loop as a standalone service: a Cloudflare Worker, a Node server, or a Vercel function. It serves the same POST /api/ask contract the Astro route does, holds the ANTHROPIC_API_KEY server-side, and reads the committed digest tree. Deploy it once and point any number of sites’ overlays at it. Keyword search runs entirely in the browser, and only the answer loop needs anything deployed.

# scaffold and deploy the Worker flavor
ask endpoint init --target cloudflare
wrangler deploy            # set ANTHROPIC_API_KEY as a secret

Docusaurus

Emit the bundle into static/ from your build script, and add the script via docusaurus.config.js:

// docusaurus.config.js
export default {
  scripts: [
    {
      src: "https://cdn.jsdelivr.net/npm/@hevmind/ask/overlay.js",
      type: "module",
      "data-hev-ask-digest": "/hev-ask/",
      "data-hev-ask-endpoint": "https://docs-ask.example.workers.dev/api/ask",
    },
  ],
};
// package.json — bundle into the static dir before docusaurus build
"scripts": {
  "build": "ask digest bundle --out static/hev-ask && docusaurus build"
}

Docusaurus headings carry explicit {#custom-id} anchors. The Docusaurus slug mode honors them, and ask digest verify checks every anchor against the built build/ HTML.

VitePress

Bundle into .vitepress/public/, then register the overlay in your theme:

// .vitepress/theme/index.ts
import DefaultTheme from "vitepress/theme";
import { mountHevAsk } from "@hevmind/ask/overlay";

export default {
  extends: DefaultTheme,
  enhanceApp() {
    if (typeof window !== "undefined") {
      mountHevAsk({ digest: "/hev-ask/", endpoint: import.meta.env.VITE_ASK_ENDPOINT });
    }
  },
};

MkDocs

Bundle into docs/hev-ask/ and reference the script with extra_javascript:

# mkdocs.yml
extra_javascript:
  - hev-ask/overlay.js

Any static site

There’s no framework to satisfy. Run ask digest bundle as your build or release step, deploy its output alongside your HTML, and drop the <script> tag into your template. Add the endpoint attribute when you want answers.

Support at a glance

FrameworkDigest buildKeyword overlayAgentic answersAdapter
AstrohevAsk() integrationSearchOverlay.astromounted /api/ask routeturnkey
Docusaurusask digest in build<script> drop-inhostable endpointdrop-in
VitePressask digest in buildtheme mountHevAskhostable endpointdrop-in
MkDocsask digest in buildextra_javascripthostable endpointdrop-in
Static / HTMLask digest in CI<script> drop-inhostable endpointdrop-in

The CLI and MCP surfaces are host-neutral on every row: a coding agent reads the same digest no matter what renders the docs. For the design behind this split, see Concepts and Tradeoffs.

esc