Mantine NextJS + Fumadocs

Docs

Menu

Guides

Search

Full-text search with Orama and Mantine Spotlight

The template ships a complete full-text search: the index is built by Orama from your docs content, and the dialog is a Mantine Spotlight. Try it now with ⌘K (or /).

How it works

The index

app/api/search/route.ts builds an Orama index from the content source at startup — no separate indexing command, the index is always in sync with your content:

app/api/search/route.ts

import { createFromSource } from 'fumadocs-core/search/server';

export const { GET } = createFromSource(source, {
  language: config.search.language,
});

The client hook

components/docs/DocsSearch.tsx uses the headless useDocsSearch hook, which debounces the query and fetches /api/search:

components/docs/DocsSearch.tsx

const { search, setSearch, query } = useDocsSearch({ type: 'fetch' });

The dialog

Results are grouped by page, heading and text. Matches arrive wrapped in <mark> tags and are rendered with the Mantine Mark component.

Static export

For a serverless deployment (e.g. GitHub Pages) the template ships a built-in static mode — no code changes required:

Terminal

yarn build:static

With NEXT_PUBLIC_STATIC_EXPORT=1 the whole Orama index is pre-rendered as a static file at /api/search, and the search dialog automatically switches to useDocsSearch({ type: 'static' }): the index is downloaded once and queried in the browser. The repository also includes a ready-made GitHub Actions workflow (.github/workflows/deploy-pages.yml) that publishes the static build to GitHub Pages on every push to main — set NEXT_PUBLIC_BASE_PATH there if the site is served under a sub-path.

Language

Stemming and tokenization follow the language configured in config/index.ts:

config/index.ts

search: {
  language: 'english',
},