Describe the bug
The "Number of stories shown" setting is ignored after a page reload when any content filters are enabled.
To Reproduce
Steps to reproduce the behavior:
- Open
news.kagi.com
- Settings → Filters: enable any content filter
- Settings → Stories: set "Number of stories shown" to 3
- Reload the page
Expected behavior
3 stories are displayed
Screenshots
N/A
Environment (please complete the following information):
- Browser: Android Firefox 154; also reproduced in desktop Firefox and Chromium. Logged-out, no sync.
Additional context
The filter does not need to match or hide any stories; merely being enabled triggers it.
Workaround: Move the "Number of stories shown" slider to any value and back restores the limit until the next reload.
LLM findings
Two code paths meet here:
1. src/lib/data/setting.svelte.ts (this repo) — number-typed settings round-trip as strings
save() stores numbers via String(this.currentValue) (lines 96–102), and load() only JSON-parses stored values starting with {/[ or equal to true/false (lines 58–68) — everything else is kept as a string. So after every reload, displaySettings.storyCount is the string "3", not the number 3. The slider's setter writes real numbers (Math.max(3, Math.min(12, value))), which is why touching the slider repairs the session.
2. Deployed build — strict limit guard in the filter-aware limiter
In the deployed bundle, when the content filter is active, the story limit is passed into a filter-aware filterStories(stories, keywords, scope, mode, limit) whose guard is:
const l = (i !== null && Number.isFinite(i)) ? i : null;
Number.isFinite("3") is false (it never coerces), so the limit is treated as absent and the full list renders. When no filter is active, the limit flows into stories.slice(0, limit) instead, and slice coerces the string — which is why the bug only manifests with filters on. Note the public repo's filterStories (src/lib/utils/contentFilter.ts) takes no limit parameter and StoryList.svelte slices before filtering, so the guard only exists in the deployed variant.
Other observations consistent with this mechanism:
- SSR renders the correct count (the
kn_prefs cookie stores a real number), so a brief flash of the correct count is visible before hydration replaces the list
- The limit drop is silent — no console output marks it
- Reproduces in a private window with just the filter enabled; clearing site data doesn't help (re-saving the setting re-creates the string)
- The nudge workaround works because the slider setter writes a real number, which passes the guard
Suggested fixes
- This repo (fixes the class): make
Setting round-trip types correctly — save(): use JSON.stringify for non-string primitives; load(): parse JSON-representable values (or at minimum, parse numeric strings for number-typed settings). Every number-typed setting currently comes back as a string after reload.
- Deployed code (belt and braces): coerce before the guard —
Number.isFinite(Number(i)) — so a string limit can't silently disable the cap.
Describe the bug
The "Number of stories shown" setting is ignored after a page reload when any content filters are enabled.
To Reproduce
Steps to reproduce the behavior:
news.kagi.comExpected behavior
3 stories are displayed
Screenshots
N/A
Environment (please complete the following information):
Additional context
The filter does not need to match or hide any stories; merely being enabled triggers it.
Workaround: Move the "Number of stories shown" slider to any value and back restores the limit until the next reload.
LLM findings
Two code paths meet here:1.
src/lib/data/setting.svelte.ts(this repo) — number-typed settings round-trip as stringssave()stores numbers viaString(this.currentValue)(lines 96–102), andload()only JSON-parses stored values starting with{/[or equal totrue/false(lines 58–68) — everything else is kept as a string. So after every reload,displaySettings.storyCountis the string"3", not the number3. The slider's setter writes real numbers (Math.max(3, Math.min(12, value))), which is why touching the slider repairs the session.2. Deployed build — strict limit guard in the filter-aware limiter
In the deployed bundle, when the content filter is active, the story limit is passed into a filter-aware
filterStories(stories, keywords, scope, mode, limit)whose guard is:Number.isFinite("3")isfalse(it never coerces), so the limit is treated as absent and the full list renders. When no filter is active, the limit flows intostories.slice(0, limit)instead, andslicecoerces the string — which is why the bug only manifests with filters on. Note the public repo'sfilterStories(src/lib/utils/contentFilter.ts) takes no limit parameter andStoryList.svelteslices before filtering, so the guard only exists in the deployed variant.Other observations consistent with this mechanism:
kn_prefscookie stores a real number), so a brief flash of the correct count is visible before hydration replaces the listSuggested fixes
Settinground-trip types correctly —save(): useJSON.stringifyfor non-string primitives;load(): parse JSON-representable values (or at minimum, parse numeric strings for number-typed settings). Every number-typed setting currently comes back as a string after reload.Number.isFinite(Number(i))— so a string limit can't silently disable the cap.