Modules
Search
2 min read
Search
/module-search adds instant full-text search to your site. At build time it generates a JSON search index from all your content. The island loads it lazily and searches entirely client-side using MiniSearch — no Cloudflare Worker or server required.
Installation
pnpm add @stedefast/module-search
Setup
// stedefast.config.ts
import { defineConfig } from "@stedefast/core";
import { SearchModule } from "@stedefast/module-search";
export default defineConfig({
// ...
modules: [
SearchModule({
fields: ["title", "description", "tags"],
hotkey: true,
}),
],
});
No Cloudflare bindings are required — search is entirely static.
Adding the search button to your theme
Import SearchButton from the module and place it in your header:
// theme/partials/header.tsx
import { SearchButton } from "@stedefast/module-search/island";
export default function Header({ site }) {
return (
<header>
<a href="/">{site.title}</a>
<SearchButton label="Search…" />
</header>
);
}
Keyboard shortcut
With hotkey: true (the default), visitors can open the search dialog with ⌘K on Mac or Ctrl+K on Windows/Linux. Set hotkey: false to disable it.
How it works
- Build time —
buildStaticExportiterates all content nodes, strips HTML from excerpts, builds a MiniSearch index, and writes it todist/data/search/index.json - Page load — nothing is loaded upfront; the index is fetched lazily the first time the dialog opens
- Search — MiniSearch performs fuzzy, prefix-aware full-text search entirely in the browser with title matches ranked higher than body text
Config reference
| Option | Type | Default | Description |
|---|---|---|---|
fields |
string[] |
["title","description","tags"] |
Front matter fields to include in the index |
hotkey |
boolean |
true |
Enable ⌘K / Ctrl+K shortcut |
excludeTypes |
string[] |
[] |
Content types to exclude from the index |
excerptLength |
number |
500 |
Max characters of body text indexed per page |
Performance
For a 500-page site, index.json is typically 200–400KB. To reduce index size on large sites:
- Set
excerptLength: 0to exclude body text (index titles and descriptions only) - Use
excludeTypes: ["note"]to skip content types that don't need to be searchable
Notes
- The search dialog is accessible: it uses
<dialog>,aria-modal, and a focus trap - Keyboard navigation: arrow keys move between results, Enter navigates, Escape closes
- For very large sites (>1000 pages), a future D1-backed Worker variant is planned — see the writing a module guide for how to build your own