The symptom

Added client-side search to this site using PaperMod’s built-in feature. Worked immediately, which should have been my first clue something was off, because it worked badly. Searching “kyber,” the full, exact word, appearing in exactly one post, returned close to a dozen completely unrelated results. Searching just “ky” returned the one correct result and nothing else. Backwards from how search should behave, more specific input giving worse results than less specific input.

First attempt, which did nothing

Set this in hugo.toml, assuming it was the actual control for fuzziness:

[params]
  fuzzysearch = true

Tested it. Broken results. Flipped it to false:

[params]
  fuzzysearch = false

Rebuilt, redeployed. Zero change in behaviour either way, “kyber” still returned the same pile of unrelated posts.

Second attempt, assuming it was a caching problem

At this point I figured Hugo was serving a stale search index from somewhere, since a config change producing literally no difference usually means old output is still being served. Did a full clean rebuild instead of the normal deploy script:

cd ~/hugo/kingtolga
rm -rf public resources
hugo --minify --cleanDestinationDir
sudo /home/tolga/hugo-deploy.sh

Also tried running hugo-deploy as the shorter installed command and hit a wall I’d forgotten about:

sudo hugo-deploy
sudo: hugo-deploy: command not found

Turned out the move into /usr/local/bin from earlier never actually happened on this box, so I fell back to the full path. Redeployed with the clean build. Still broken. Same results, exact word search still pulling in unrelated posts. At this point the setting itself was the actual problem, not caching, and I’d wasted a rebuild cycle chasing the wrong theory.

Actually finding the real mechanism

Stopped guessing at config values entirely and went into the theme’s own source to see what it was actually reading:

grep -r "fuzzysearch\|fuse\|lunr" ~/hugo/kingtolga/themes/PaperMod/layouts/_partials/*.html ~/hugo/kingtolga/themes/PaperMod/assets/js/*.js

That surfaced it. PaperMod’s search runs on Fuse.js, and the actual options object it reads is site.Params.fuseOpts, a nested table with real Fuse.js configuration keys. fuzzysearch was never a parameter this theme checks for at all. I’d invented a setting that happened to parse as valid TOML and did precisely nothing, twice, in two different values, across two rebuilds.

The real fix

[params.fuseOpts]
  isCaseSensitive = false
  shouldSort = true
  location = 0
  distance = 0
  threshold = 0.0
  minMatchCharLength = 3
  keys = ["title", "permalink", "summary", "content"]

Removed the fake fuzzysearch line entirely first:

sed -i '/^  fuzzysearch = false/d' ~/hugo/kingtolga/hugo.toml

threshold is the setting that actually mattered. Fuse.js scores matches on a 0 to 1 scale, 0.0 means only an exact match counts, 1.0 matches almost anything. Left unset, it defaults to roughly 0.4, which explains exactly what I was seeing the whole time: loose, low confidence matches scattered across posts that never actually contained the search term.

distance = 0 tightens it further by removing tolerance for how far a matched substring can sit from where Fuse.js expects it in the text. minMatchCharLength = 3 stops it from trying to match on one or two characters at all, which is why “ky” alone was returning a real result the whole time, that result was legitimate, just riding alongside a threshold loose enough to also return everything else.

Applying it, correctly this time

cd ~/hugo/kingtolga
rm -rf public resources
sudo /home/tolga/hugo-deploy.sh

Same clean rebuild step I’d already tried once for the wrong reason, this time actually paired with a real config change. Hard refreshed the search page in the browser to rule out the browser itself caching the old Fuse.js index, then tested “kyber” and “ky” again. Fixed, finally.

What actually fixed it, and what wasted time first

fuzzysearch, invented, did nothing, tested in both true and false, cost two full rebuild cycles chasing a setting that was never real. The clean rebuild itself was the right instinct but applied at the wrong moment, it fixed nothing because the underlying config was still wrong, not stale. threshold, distance, and minMatchCharLength under the real fuseOpts table were the only things that changed the actual behaviour. Worth remembering next time a config value seems to do nothing at all, that is the signal to go check the theme’s own source immediately, rather than re-testing the same wrong parameter a second time first.