The search block provides a full-site search experience that lets visitors find any published page from a single, dedicated search page. The header includes a search icon (togglable by authors) that navigates users to this page.
Indexing is handled by the EDS platform via helix-query.yaml. It defines a pages index that crawls all published pages (excluding .json files) and extracts 7 properties — title, description, image, tags, content, lastModified, robots — into /query-index.json.
Querying is entirely client-side:
-
On block load, the query index JSON is fetched and cached in a Map. The fetch is deferred via requestIdleCallback (1500ms timeout) or triggered on first input focus — whichever comes first — to avoid impacting LCP.
-
Filter ("Search in"): A dropdown that narrows which indexed fields are searched — visitors can restrict matches to Title, Description, Content, Tags, or Path instead of the default All Fields. Under the hood, filterPages() performs case-insensitive substring matching (String.includes()) against the selected field(s), with the Title option checking three sources (actual title, navTitle, and a path-derived title). Changing the filter re-runs the search instantly with no debounce, and the selection persists in the URL as ?filter=.
-
Sort ("Sort by"): A dropdown that reorders the filtered results by Most Relevant (default), Least Relevant, Title A–Z, or Title Z–A. Relevance is a cumulative score computed per result — exact title matches score highest (100pts), followed by tags (25pts), description (15pts + 3/occurrence), and body content (1/occurrence) — so well-authored pages with strong metadata naturally rank at the top. Title sorting uses localeCompare() for proper alphabetical ordering. Like filter, changing the sort is instant and persists as ?sort= in the URL.
-
Results are rendered via DocumentFragment for batched DOM writes, with replaceChildren() to avoid flicker. An LRU cache (500 entries) optimizes repeated stripHTML() calls. Input is debounced at 300ms.
-
All user-generated content is run through escapeHTML() before rendering, and result links are validated to start with / to prevent XSS.
-
Search results are plugged into Pagination engine automatically (utilizes Pagination block functionality).
File footprint: The entire search feature is self-contained in blocks/search/, plus the shared pagination engine in blocks/pagination/pagination.js. No external search service or server-side API is involved.