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
| Prop | Type | Default | Description |
|---|---|---|---|
endpoint | string | '/api/ask' | Endpoint the overlay posts queries to. Must match the integration’s endpoint option. |
placeholder | string | 'Search the docs…' | Placeholder text for the input. |
debounce | number | 500 | Milliseconds 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-Kis bound automatically once the component is on the page.- Any element with
data-hev-ask-openopens 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
Tabto 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.
Keyword results and deep links
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 whereask digest bundlewrote 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
| Framework | Digest build | Keyword overlay | Agentic answers | Adapter |
|---|---|---|---|---|
| Astro | hevAsk() integration | SearchOverlay.astro | mounted /api/ask route | turnkey |
| Docusaurus | ask digest in build | <script> drop-in | hostable endpoint | drop-in |
| VitePress | ask digest in build | theme mountHevAsk | hostable endpoint | drop-in |
| MkDocs | ask digest in build | extra_javascript | hostable endpoint | drop-in |
| Static / HTML | ask digest in CI | <script> drop-in | hostable endpoint | drop-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.