In .NET development, DocFx is an incredibly useful tool for automatically generating API documentation. However, the default built-in search powered by lunr.js can sometimes deliver underwhelming results, leading to a suboptimal user experience.
In this article, I will show you how to easily replace it and supercharge your documentation's search functionality using Pagefind, a highly performant and lightweight static search engine.
Prerequisites
- This guide assumes you are using DocFx with the
moderntemplate (available in DocFx v2.70+). - This implementation utilizes the official Pagefind Component UI.
Step-by-Step Implementation
1. Disable the Default Search
First, disable DocFx's built-in search function by updating your configuration file.
docfx.json
"globalMetadata": {
"_enableSearch": false
}
2. Create a Custom Template to Inject Pagefind UI
Next, create a custom template file to inject the Pagefind search box into your navigation bar.
template/public/main.js
export default {
start: () => {
setupPagefind();
},
};
function setupPagefind() {
// Prevent duplicate initialization
if (document.getElementById("pagefind-modal-container")) {
return;
}
const navContainer = document.querySelector("#navbar");
if (!navContainer) {
console.error("#navbar was not found.");
return;
}
// Inject Pagefind UI CSS
if (!document.querySelector('link[href*="pagefind-component-ui.css"]')) {
const link = document.createElement("link");
link.href = "pagefind/pagefind-component-ui.css";
link.rel = "stylesheet";
document.head.appendChild(link);
}
// Inject Pagefind UI JS
if (!document.querySelector('script[src*="pagefind-component-ui.js"]')) {
const script = document.createElement("script");
script.src = "pagefind/pagefind-component-ui.js";
script.type = "module";
document.head.appendChild(script);
}
// Create and append the search modal container
const modalContainer = document.createElement("div");
modalContainer.id = "pagefind-modal-container";
modalContainer.className = "d-flex align-items-center order-last";
modalContainer.innerHTML = `
<pagefind-config bundle-path="/pagefind/"></pagefind-config>
<pagefind-modal-trigger></pagefind-modal-trigger>
<pagefind-modal></pagefind-modal>
`;
navContainer.appendChild(modalContainer);
}
Now, update your docfx.json to include your custom template folder. Make sure your custom template is listed after the modern template to properly override it.
docfx.json
"template": [
"default",
"modern",
"template" // <-- Add your custom template folder here
]
3. Build DocFx and Run Pagefind Indexing
Build your DocFx site as usual, then run Pagefind to index the generated static files inside the _site directory.
dotnet docfx build docfx.json
npx -y pagefind --site _site
4. Serve the Site and Test
Run the DocFx local server to open your browser and see the new Pagefind search box in action.
dotnet docfx serve _site --open-browser
⚠️ Important Note for Subdirectory Hosting (e.g., GitHub Pages)
If you host your site in a subdirectory (which is common with GitHub Pages), you must update the bundle-path in your template/public/main.js to match your subdirectory structure.
Example: If your site URL is
https://<username>.github.io/<repository-name>/, modify the template code like this:
modalContainer.innerHTML = `
<pagefind-config bundle-path="/{repository-name}/pagefind/"></pagefind-config>
<pagefind-modal-trigger></pagefind-modal-trigger>
<pagefind-modal></pagefind-modal>
`;
Live Demo & Source Code
You can see this integration in action and check out the full repository here:
- Live Demo Site: https://nullmake.github.io/calm-dotnet/
- Source Code: GitHub Repository (documents folder)
Happy documenting! If you have any questions or feedback, feel free to leave a comment below.



Top comments (0)