Skip to content

added new improved searchbar functionality#523

Open
antedotee wants to merge 1 commit into
krkn-chaos:mainfrom
antedotee:update-search-functionality
Open

added new improved searchbar functionality#523
antedotee wants to merge 1 commit into
krkn-chaos:mainfrom
antedotee:update-search-functionality

Conversation

@antedotee

Copy link
Copy Markdown
Contributor

Shifted the searchbar position and now instead of just giving the section, it gives the exact place in where inside the section that keyword is written, making it more close to the docs-search functionality available on other sites.

Fixes #512

Signed-off-by: antedotee <soniyadav2051982@gmail.com>
@netlify

netlify Bot commented Jun 5, 2026

Copy link
Copy Markdown

Deploy Preview for krkn-chaos ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 7dd862d
🔍 Latest deploy log https://app.netlify.com/projects/krkn-chaos/deploys/6a2303e6a928200008996188
😎 Deploy Preview https://deploy-preview-523--krkn-chaos.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Implement custom Cmd+K search overlay with Lunr integration

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Replaced Docsy's offline search with custom Cmd+K overlay powered by Lunr index
• Added live-as-you-type search with highlighted snippets and keyboard navigation
• Implemented new search UI with breadcrumb paths and result excerpts
• Integrated krkn-search.js for independent site search functionality
Diagram
flowchart LR
  A["Docsy Offline Search"] -->|replaced| B["Custom Cmd+K Overlay"]
  C["Lunr Index"] -->|reused| B
  B -->|renders| D["Live Results with Snippets"]
  E["krkn-search.js"] -->|powers| B
  F["Keyboard Navigation"] -->|enhances| B

Loading

Grey Divider

File Changes

1. layouts/_partials/hooks/body-end.html ✨ Enhancement +3/-0

Load custom search script

• Added script tag to load krkn-search.js for custom search functionality
• Positioned after scroll-animations script and before custom page scripts

layouts/_partials/hooks/body-end.html


2. layouts/_partials/navbar.html ✨ Enhancement +27/-22

Refactor search overlay with custom input and results

• Replaced Docsy's inline search input with custom krkn-search-overlay__input element
• Added ARIA attributes for accessibility (combobox, listbox, autocomplete)
• Moved Docsy's search-input partial into hidden wrapper to expose Lunr index URL
• Updated search trigger logic to use input event instead of change event
• Added dedicated results container with krkn-search-results ID
• Updated keyboard hints to show arrow keys, Enter, and Escape

layouts/_partials/navbar.html


3. assets/scss/_custom_navbar.scss ✨ Enhancement +150/-49

Redesign search overlay styles and result rendering

• Hid Docsy's sidebar search and index-source wrapper with display: none
• Simplified search input styling by removing Docsy-specific selectors
• Added native search field decoration hiding for webkit browsers
• Redesigned hint section with flexbox layout and keyboard key styling
• Replaced Docsy's popover results styling with new krkn-search-overlay__results container
• Added result item styling with title, path breadcrumb, and excerpt with highlighted matches
• Implemented smooth max-height transition for results container

assets/scss/_custom_navbar.scss


View more (2)
4. static/js/krkn-search.js ✨ Enhancement +285/-0

Implement custom Lunr-powered search engine

• Created new 285-line search module implementing Cmd+K overlay functionality
• Loads and builds Lunr index from Hugo-generated offline search data
• Implements live-as-you-type search with debouncing and query tokenization
• Provides full keyboard navigation (arrow keys, Enter, Escape)
• Generates context snippets centered on matched terms with highlighted keywords
• Renders breadcrumb paths from document references
• Handles edge cases like malformed entries and failed index loads

static/js/krkn-search.js


5. hugo.yaml ⚙️ Configuration changes +6/-3

Update configuration and documentation

• Updated comments explaining that Lunr index is generated inline at build time
• Clarified that custom krkn-search.js renders results in Cmd+K overlay
• Changed sidebar_search_disable from false to true to hide sidebar search box
• Added comment explaining sidebar search is hidden in favor of Cmd+K overlay

hugo.yaml


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Jun 5, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0)

Context used

Grey Divider


Action required

1. Stale results race 🐞 Bug ≡ Correctness
Description
runSearch() increments queryToken only when the debounced search begins, so if the user edits the
query while an earlier search is running (before the next debounced runSearch fires), the earlier
search can still render results that no longer match the current input.
Code

static/js/krkn-search.js[R96-129]

+  function onInput() {
+    var query = input.value.trim();
+    clearTimeout(debounceTimer);
+
+    if (!query) { renderState(''); return; }
+    if (loadFailed) { failLoad(); return; }
+    if (!idx) {
+      loadIndex();
+      renderState('<div class="krkn-search-msg">Loading search…</div>');
+      return;
+    }
+    debounceTimer = setTimeout(function () { runSearch(query); }, DEBOUNCE_MS);
+  }
+
+  function runSearch(query) {
+    var token = ++queryToken;
+    var lunr = window.lunr;
+    var terms = tokenize(query);
+
+    var matches;
+    try {
+      matches = idx.query(function (q) {
+        terms.forEach(function (term) {
+          q.term(term, { boost: 100 });
+          q.term(term, { wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING, boost: 10 });
+          q.term(term, { editDistance: 2 });
+        });
+      });
+    } catch (e) {
+      matches = [];
+    }
+    if (token !== queryToken) return;
+    renderResults(query, terms, matches);
+  }
Evidence
onInput() schedules a debounced runSearch(query) without changing queryToken, while runSearch()
increments queryToken and uses it to decide whether results are stale; this allows an older search
to render if the user changes the input before the next runSearch starts.

static/js/krkn-search.js[96-129]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`queryToken` is incremented inside `runSearch()`, not when the input changes. If the user types again while a previous `runSearch()` is executing (and before the next debounced `runSearch()` starts), the old search will still pass `token === queryToken` and render stale results.

### Issue Context
The debounce delays starting the next search, which leaves a window where the current query has changed but `queryToken` has not.

### Fix Focus Areas
- static/js/krkn-search.js[96-129]

### Suggested fix
- Increment a version/token in `onInput()` immediately when the query changes.
- Capture that token when scheduling the debounced work, and pass it into `runSearch(query, token)`.
- In `runSearch`, before calling `renderResults`, verify the token still matches the latest token **and** (optionally) the current `input.value.trim()` still equals the query being rendered.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Index load can’t retry 🐞 Bug ☼ Reliability
Description
If the index fetch fails once, loadStarted remains true and loadFailed remains true, so subsequent
focus/input attempts cannot re-run loadIndex() and search stays unavailable until a full page
reload.
Code

static/js/krkn-search.js[R52-106]

+  function loadIndex() {
+    if (loadStarted) return;
+    loadStarted = true;
+
+    var srcEl = document.querySelector('[data-offline-search-index-json-src]');
+    var url = srcEl && srcEl.getAttribute('data-offline-search-index-json-src');
+    if (srcEl && srcEl.getAttribute('data-offline-search-base-href')) {
+      baseHref = srcEl.getAttribute('data-offline-search-base-href');
+    }
+    if (!url) { failLoad(); return; }
+
+    fetch(url)
+      .then(function (r) { return r.json(); })
+      .then(function (data) { buildIndex(data); })
+      .catch(function () { failLoad(); });
+  }
+
+  function buildIndex(data) {
+    if (typeof window.lunr === 'undefined' || !Array.isArray(data)) { failLoad(); return; }
+    var lunr = window.lunr;
+    idx = lunr(function () {
+      var self = this;
+      self.ref('ref');
+      self.field('title', { boost: 5 });
+      self.field('categories', { boost: 3 });
+      self.field('tags', { boost: 3 });
+      self.field('description', { boost: 2 });
+      self.field('body');
+      data.forEach(function (doc) {
+        try { self.add(doc); } catch (e) { /* skip malformed entry */ }
+        docMap[doc.ref] = { title: doc.title, body: doc.body || '', excerpt: doc.excerpt || '' };
+      });
+    });
+    // If the user already typed before the index finished loading, search now.
+    if (input.value.trim()) onInput();
+  }
+
+  function failLoad() {
+    loadFailed = true;
+    renderState('<div class="krkn-search-msg">Search is unavailable right now.</div>');
+  }
+
+  // ---- Input handling -----------------------------------------------------
+
+  function onInput() {
+    var query = input.value.trim();
+    clearTimeout(debounceTimer);
+
+    if (!query) { renderState(''); return; }
+    if (loadFailed) { failLoad(); return; }
+    if (!idx) {
+      loadIndex();
+      renderState('<div class="krkn-search-msg">Loading search…</div>');
+      return;
+    }
Evidence
loadIndex() sets loadStarted=true and returns early on subsequent calls; on failure failLoad() sets
loadFailed=true, and onInput() bails out when loadFailed is true—together preventing any retry path
without reloading the page.

static/js/krkn-search.js[52-67]
static/js/krkn-search.js[89-106]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
After any load failure, the current state machine prevents retrying index load: `loadStarted` stays `true` (blocking `loadIndex()`), and `loadFailed` causes `onInput()` to short-circuit.

### Issue Context
Transient failures (missing file during dev, temporary fetch error, partial build, etc.) will permanently disable search for the session.

### Fix Focus Areas
- static/js/krkn-search.js[52-67]
- static/js/krkn-search.js[89-106]

### Suggested fix
- In `failLoad()`, reset `loadStarted = false` so future focus/input can re-attempt.
- Consider only setting `loadFailed = true` after a threshold of attempts, or track `loadError` and allow a retry on next focus.
- Optionally add a small “Retry” UI state that calls `loadIndex()` again.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@antedotee

Copy link
Copy Markdown
Contributor Author

Have a look when free @paigerube14.

Comment thread static/js/krkn-search.js
Comment on lines +96 to +129
function onInput() {
var query = input.value.trim();
clearTimeout(debounceTimer);

if (!query) { renderState(''); return; }
if (loadFailed) { failLoad(); return; }
if (!idx) {
loadIndex();
renderState('<div class="krkn-search-msg">Loading search…</div>');
return;
}
debounceTimer = setTimeout(function () { runSearch(query); }, DEBOUNCE_MS);
}

function runSearch(query) {
var token = ++queryToken;
var lunr = window.lunr;
var terms = tokenize(query);

var matches;
try {
matches = idx.query(function (q) {
terms.forEach(function (term) {
q.term(term, { boost: 100 });
q.term(term, { wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING, boost: 10 });
q.term(term, { editDistance: 2 });
});
});
} catch (e) {
matches = [];
}
if (token !== queryToken) return;
renderResults(query, terms, matches);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Stale results race 🐞 Bug ≡ Correctness

runSearch() increments queryToken only when the debounced search begins, so if the user edits the
query while an earlier search is running (before the next debounced runSearch fires), the earlier
search can still render results that no longer match the current input.
Agent Prompt
### Issue description
`queryToken` is incremented inside `runSearch()`, not when the input changes. If the user types again while a previous `runSearch()` is executing (and before the next debounced `runSearch()` starts), the old search will still pass `token === queryToken` and render stale results.

### Issue Context
The debounce delays starting the next search, which leaves a window where the current query has changed but `queryToken` has not.

### Fix Focus Areas
- static/js/krkn-search.js[96-129]

### Suggested fix
- Increment a version/token in `onInput()` immediately when the query changes.
- Capture that token when scheduling the debounced work, and pass it into `runSearch(query, token)`.
- In `runSearch`, before calling `renderResults`, verify the token still matches the latest token **and** (optionally) the current `input.value.trim()` still equals the query being rendered.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The search functionality on the website can be improved

1 participant