This documentation is also published as Markdown for efficient machine reading: the whole site is indexed at /llms.txt, and every page has a clean Markdown copy at the same URL with .md appended. These are generated from the same source and cost far fewer tokens to read than this rendered HTML.

Skip to main content

May 26, 2026

Search that lands on the right heading

By Phil Scott

Search used to point at a page and leave you to find the part you wanted. Now it points at the heading.

Results at the heading level

When a page renders, Pennington splits its HTML into one record per heading, each carrying the page-to-heading trail. A query for "base URL" returns the exact section that covers it, and the link drops you at /page/#that-heading rather than the top of a long page. It's the model DocSearch uses, built at your site's build time instead of crawled afterward.

The engine underneath is DeweySearch, a .NET full-text index: Pennington builds the index, DeweySearch tokenizes, stems, and ranks. There's no search server and no third-party service. The index is static JSON, sharded per locale under /search/{locale}/, and the browser queries it directly.

The client loads on demand

The search client is lazy. A page ships no search JavaScript until you open the box; the client script loads then, and the index downloads on the first keystroke. A site nobody searches never pays for search. The search how-to covers turning it on, and search on a bare host wires the modal into a non-template site.

Tuning what ranks

By default, an exact title match wins: search "DocSiteOptions" and the type's own page sits above the API-reference entries that merely mention it. Beyond that, you can weight a URL prefix or a content area, add synonyms, and turn on facet filters through SearchIndexOptions. The reasoning behind the heading-level model is in how search works.