Pagefind
Keep your custom Pagefind result renderer. Hosted retrieval replaces the static index, so PDFs, Office files and scanned documents become searchable alongside your pages.
On this page
1Install
# Needs @docslurp/sdk 0.2.0 or newer (0.1.x lacks these exports).
npm install @docslurp/sdk@^0.3.0
# Then import:
# import { createDocSlurpPagefind } from '@docslurp/sdk/search-adapters';# Same client as @docslurp/sdk/search-adapters, one subpath per search client.
npm install @docslurp/contrib-search-compat
# Then import:
# import { createDocSlurpPagefind } from '@docslurp/contrib-search-compat/pagefind';2Swap the module
Replace the dynamic import of pagefind.js with the DocSlurp adapter. Everything after search() keeps working.
- const pagefind = await import('/pagefind/pagefind.js');
+ import { createDocSlurpPagefind } from '@docslurp/sdk/search-adapters';
+ const pagefind = createDocSlurpPagefind({
+ apiUrl: 'https://docslurp.io',
+ clientKey: PUBLIC_DOCSLURP_CLIENT_KEY,
+ workspaceId: 'product-docs',
+ resolveUrl: hit => publicUrls[hit.citation.documentId], // your real routes
+ });
// Unchanged: search(term) and lazy results[].data()
const search = await pagefind.search('installation');
const first = await search.results[0]?.data();3Map source URLs
Pagefind results link to pages; DocSlurp results cite documents. resolveUrl is required: map each citation.documentId to the real public page that published it, for example from a JSON map you write while ingesting. It must return an https:// or site-relative URL for every hit, or the search throws rather than guessing a link.
Usage
import { createDocSlurpPagefind } from '@docslurp/sdk/search-adapters';
// Map DocSlurp document IDs to the public pages that published them.
const publicUrls: Record<string, string> = await fetch('/search-map.json').then(r => r.json());
const pagefind = createDocSlurpPagefind({
apiUrl: 'https://docslurp.io',
clientKey: import.meta.env.PUBLIC_DOCSLURP_CLIENT_KEY,
workspaceId: 'product-docs',
resolveUrl: hit => publicUrls[hit.citation.documentId],
});
const search = await pagefind.search('installation');
for (const result of search.results.slice(0, 5)) {
const data = await result.data();
render({ url: data.url, title: data.meta.title, excerpt: data.excerpt }); // excerpt is HTML-escaped
}{
"url": "/docs/install",
"meta": { "title": "install-guide.pdf" },
"excerpt": "Install the CLI with npm, then set DOCSLURP_API_KEY.",
"plain_excerpt": "Install the CLI with npm, then set DOCSLURP_API_KEY.",
"word_count": 42,
"filters": {},
"anchors": [],
"sub_results": [],
"citation": { "documentId": "8f1c…", "filename": "install-guide.pdf", "pageNumbers": [3], "chunkIndex": 12 }
}curl https://docslurp.io/compat/pagefind/product-docs/search \
-H "Authorization: Bearer $DOCSLURP_SEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{ "term": "installation" }'The HTTP endpoint returns the same JSON without lazy data() wrappers. Without your URL map, its url is only filled when a result already carries a public source URL.
Compatibility
Supported
search(term),results[].data(),filters()returning{}url,meta.title,excerpt(HTML-escaped) andplain_excerptcitationon every result for page-level source links- Up to 100 ranked passages per query
Watch for
- Stock Pagefind UI and offline index loading are out of scope. Use the Astro component, the widget or your own renderer.
- Non-empty
filtersorsortthrow a compatibility error. - Excerpts have no synthetic
<mark>highlights.
Hand off to an agent
Working in a real codebase? Copy a prompt that tells a coding agent exactly what to change for Pagefind: which entry point to use, the supported contract, and what to validate before shipping. It contains no keys or secrets.
Review agent instructions
Before switching traffic, run through the go-live checklist. Stuck? See troubleshooting.