aboutsummaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
...
| * fix: replace IntersectionObserver with scroll-position check for infinite scrollClaude8 days4-76/+75
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The IntersectionObserver approach for infinite scroll was unreliable — items would not load when scrolling to the bottom in v3, while v1's polling approach worked fine. The issue was that IntersectionObserver with a custom root element (main-content, whose height comes from flex align-items:stretch rather than an explicit height) didn't fire reliably, and renderItems() being called 3 times per fetch cycle (from both items-updated and loading-state-changed events) kept destroying and recreating the observer. Replace with a simple scroll-position check in the existing onscroll handler, matching v1's proven approach: when the user scrolls within 200px of the bottom of #main-content, trigger loadMore(). This runs on every scroll event (cheap arithmetic comparison) and only fires when content actually overflows the container. Remove the unused itemObserver module-level variable. Update regression tests to simulate scroll position instead of IntersectionObserver callbacks, with 4 cases: scroll near bottom triggers load, scroll far from bottom doesn't, loading=true blocks, and hasMore=false hides sentinel. https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* | Merge pull request #10 from adammathes/claude/fix-open-tickets-IVV1CAdam Mathes8 days4-12/+107
|\| | | | | fix: store sentinel IntersectionObserver in module-level variable to …
| * fix: store sentinel IntersectionObserver in module-level variable to prevent GCClaude8 days4-12/+107
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The load-more sentinel observer was assigned to a local `const observer` that fell out of scope after renderItems() returned. Without a persistent JS reference, engines can garbage-collect the observer, silently breaking infinite scroll (no more items loaded on scroll). Fix: assign to the existing module-level `itemObserver` variable, which is already disconnected/replaced at the top of each renderItems() call. Add three regression tests in regression.test.ts that use a class-based IntersectionObserver mock to capture the callback and verify: - sentinel visible → loadMore fires - sentinel visible while loading → loadMore suppressed - hasMore=false → no sentinel rendered, no loadMore https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* | Merge pull request #9 from adammathes/claude/fix-open-tickets-IVV1CAdam Mathes8 days14-83/+432
|\| | | | | Update benchmarks, fix SSRF proxy bypass, and refactor frontend sidebar layout
| * ci: upgrade golangci-lint-action v4 -> v6Claude8 days1-1/+1
| | | | | | | | | | | | golangci-lint-action@v4 passes --out-format=github-actions which is an unknown flag in golangci-lint v2.x. @v6 was released to support v2.x and matches the v2.9.0 binary version already specified.
| * test: loosen DOM insertion perf thresholds for slow CI runnersClaude8 days2-6/+6
| | | | | | | | | | | | | | | | 100-item DOM insertion: 200ms -> 500ms (CI took 260ms, 2x headroom) 500-item DOM insertion: update test name to match actual 1400ms threshold (the 1400ms limit was already in code; test name was stale) Update benchmarks-02.md to reflect corrected thresholds.
| * build: rebuild frontend dist (fix ui-check CI failure)Claude8 days4-9/+14
| | | | | | | | | | Source changes since last dist commit shifted Vite content hashes. Rebuilding ensures web/dist/v3/ matches a fresh `make ui-vanilla`.
| * DOCS: split benchmarks into sequential files (NK-ax2vlc)Claude8 days2-0/+120
| | | | | | | | | | | | Rename benchmarks.md -> benchmarks-02.md (2026-02-17 amd64 run with full_content benchmarks) and restore the prior 2026-02-16 arm64 run as benchmarks-01.md so sequence is clear from filenames.
| * Update thicket tickets: close resolved tickets, add future workclaude/fix-open-tickets-IVV1CClaude9 days1-8/+16
| | | | | | | | | | | | | | | | | | Closed: NK-t8qnrh, NK-mcl01m, NK-pbqvke, NK-z1czaq, NK-ekxfvv, NK-tktg7s, NK-ax2vlc, NK-26sdqp Created: NK-u9dlcx (frontend linting), NK-2ylt2b (dark mode tests), NK-q7a6kb (safehttp proxy bypass test), NK-0fjzr6 (stream benchmark) https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
| * Add regression tests for NK-t8qnrh, NK-mcl01m, NK-z1czaq (NK-26sdqp)Claude9 days1-1/+91
| | | | | | | | | | | | | | | | | | | | - NK-t8qnrh: test that item-description renders links in feed items - NK-mcl01m: test sidebar section order (filters → search → feeds → tags), and presence of "+ new" link - NK-z1czaq: test that sidebar and main-content are siblings (overlay layout) - Import renderLayout and createFeedItem into regression test suite https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
| * Update DOCS/benchmarks.md with 2026-02-17 run (NK-ax2vlc)Claude9 days1-47/+66
| | | | | | | | | | | | | | | | | | | | - Fresh benchmark data on amd64 Intel Xeon (previous was arm64) - Highlight new full_content benchmarks: 39% memory, 40% speed improvement from excluding full_content in list views (validates NK-k9otuy fix) - Update frontend perf results (all pass, DOM insertion ~324ms) - Note safehttp proxy fix in changes since last run https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
| * Re-enable GitHub CI with updated paths (NK-tktg7s)Claude9 days1-41/+10
| | | | | | | | | | | | | | | | | | | | | | - Re-enable push/PR triggers on master branch - Frontend job: use ./frontend-vanilla (was ./frontend, which no longer exists) - ui-check: check web/dist/v3/ (was web/dist/v2/) - Backend dummy assets: create web/dist/v3 (was web/dist/v2) - Remove frontend lint step (no lint script in frontend-vanilla) - Remove E2E job (disabled in Makefile, no playwright setup in v3) https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
| * Add full_content benchmarks to quantify payload savings (NK-ekxfvv)Claude9 days1-0/+77
| | | | | | | | | | | | | | | | | | Add BenchmarkFilter_15Items_WithFullContent, BenchmarkFilter_15Items_IncludeFullContent, and BenchmarkFilter_LargeDataset_WithFullContent. Items are seeded with realistic ~2KB full_content. Results show excluding full_content reduces B/op by ~40% (363KB vs 595KB for 15 items). https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
| * v3 UI: Sidebar always overlays content, never shifts it (NK-z1czaq)Claude9 days1-13/+29
| | | | | | | | | | | | | | | | Make sidebar position: fixed on desktop, same as mobile. Content area fills full viewport width and items remain centered regardless of sidebar state. Easy-to-revert CONTENT CENTERING PARAMETER comment added. https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
| * v3 UI: Fix dark mode visual bugs (NK-pbqvke)Claude9 days1-0/+33
| | | | | | | | | | | | | | | | | | | | - Sidebar uses grey background with dark text in dark mode - Sidebar toggle has no background in dark mode - Sidebar search input uses light bg with dark text in dark mode - item-description links use correct color (--link-color = #5ac8fa in dark) and no underline (fixed in prior commit) https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
| * v3 UI: Reorder sidebar sections per ticket NK-mcl01mClaude9 days2-7/+13
| | | | | | | | | | | | | | | | | | New order: filters (Unread/All/Starred) → search → "+ new" → Feeds → Tags Previously: search → filters → Tags → Feeds Also adjust sidebar-search margin now that it's inside the scroll area. https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
| * Fix link underlines in v3 UI and SSRF proxy bypassClaude9 days2-0/+6
|/ | | | | | | | | | - Add text-decoration: none to .item-description a links in v3 CSS to match v1 style (no underlines on feed item content links) - Fix safehttp to disable proxy on safe client; without this, HTTP proxy env vars bypass the DialContext SSRF check for IPs like 10.0.0.1, causing TestSafeClient to fail https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
* more tickets for claudeAdam Mathes9 days1-0/+2
|
* more tickets for claudeAdam Mathes9 days1-4/+9
|
* Complete V2 removal from Makefile and check in updated V3 production assetsAdam Mathes9 days5-17/+11
|
* Update V3 dark mode to use true black background (#000000) matching V1 ↵Adam Mathes9 days1-5/+5
| | | | legacy theme
* Remove legacy V2 React frontend and update build/test scripts to focus on ↵Adam Mathes9 days78-16978/+5
| | | | Vanilla JS (V3)
* Fix flaky V2 test by removing unused keyboard shortcut testAdam Mathes9 days1-52/+0
|
* Update V2/V3 'mark as read' logic to require item bottom to be above ↵Adam Mathes9 days5-21/+54
| | | | viewport, while keeping V1 unchanged
* Fix CSP violation on login page by moving inline script to external fileAdam Mathes9 days2-5/+13
|
* Update frontend build artifacts and fix test lint errorsAdam Mathes9 days7-23/+23
|
* Add regression test for scroll-to-read functionalityAdam Mathes9 days1-0/+138
|
* Fix scroll-to-read functionality across all UIs (V1, V2, V3)Adam Mathes9 days5-221/+298
|
* Merge pull request #8 from adammathes/claude/thicket-ready-crank-RmQuIAdam Mathes9 days10-28/+23
|\ | | | | Remove circle styling from NEKO sidebar toggle button
| * Remove circle styling from NEKO sidebar toggle buttonclaude/thicket-ready-crank-RmQuIClaude9 days10-28/+23
|/ | | | | | | Strip border-radius, box-shadow, background, and backdrop-filter from the sidebar toggle in both v2 and v3 frontends so the logo appears flat. https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
* Merge pull request #7 from adammathes/claude/thicket-ready-crank-RmQuIAdam Mathes9 days12-35/+327
|\ | | | | More crank pulls from claude
| * Add startup hook to install thicket CLIClaude9 days1-0/+1
| | | | | | | | https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
| * Add tests for CSRF exclusions, Filter includeContent, multi-feed, and routingClaude9 days5-1/+246
| | | | | | | | | | | | | | | | | | | | | | - CSRF: test excluded paths (/api/login, /api/logout), PUT/DELETE methods - Item model: test Filter includeContent flag, ItemById returns content, multiple feed_ids filtering - API: test read_filter=all param, feed_ids comma-separated filter, full_content exclusion from stream - Routing: add v3 frontend route test https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
| * Align sidebar CSS breakpoints with JS threshold at 1024pxClaude9 days6-19/+17
| | | | | | | | | | | | | | | | The sidebar default-closed JS logic used 1024px but CSS media queries used 768px, causing inconsistent behavior on tablets. Updated all sidebar-related breakpoints to 1024px/1025px to match. https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
| * Exclude full_content from stream list API responsesClaude9 days3-15/+63
| | | | | | | | | | | | | | | | | | | | | | The /stream endpoint now skips selecting full_content and header_image from the database, reducing memory allocation and response payload size for list views. Full content remains available via /item/:id endpoint. Adds omitempty to JSON tags so empty fields are omitted from responses, and a test verifying full_content is excluded from stream responses. https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
* | Merge pull request #6 from adammathes/claude/fix-mobile-scroll-read-yVmVkAdam Mathes9 days2-8/+13
|\ \ | |/ |/| Fix mobile scroll not marking items as read in v3 UI
| * Fix mobile scroll not marking items as read in v3 UIClaude9 days2-8/+13
|/ | | | | | | | | | | | | | Two issues prevented IntersectionObserver from firing on mobile: 1. threshold: 1.0 required items to be 100% visible, but on mobile viewports items with descriptions are often taller than the screen 2. root: null used the viewport, but scrolling happens inside .main-content (overflow-y: auto) while body has overflow: hidden Switched to "scrolled past" pattern: items are marked read when they scroll above the viewport (like the working legacy UI). Set root to the actual scroll container element. https://claude.ai/code/session_01NSUnBzNrgQVUNg9PnugF7N
* more ticketsAdam Mathes9 days1-4/+9
|
* v3: fix feed toggle from settings page, add navigation testsAdam Mathes9 days2-1/+36
| | | | | | | | | When on the settings page and clicking a feed that was previously active, navigate to that feed instead of toggling back to home. The toggle behavior now only applies when already viewing that feed. Added tests for navigating from settings to feeds and tags. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* DOCS: comprehensive benchmark results from full perf test suiteAdam Mathes9 days1-0/+99
| | | | | | | | | Ran Go benchmarks (3x count) across api, crawler, item model, and web middleware packages. Also ran frontend-vanilla perf tests. Documented findings including stream allocation overhead, image proxy cost, and middleware latency. Added potential improvement recommendations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Enhance CSRF protection for login pageAdam Mathes9 days3-33/+61
| | | | | | | | | | Login form now includes a CSRF token from the cookie as a hidden form field. The CSRF middleware accepts tokens from either the X-CSRF-Token header (for JS clients) or the csrf_token form field (for HTML forms). Removed /login from the CSRF exclusion list so login POSTs are now validated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* v3: persist sidebar state via cookie, default closed on tablet/mobileAdam Mathes9 days3-7/+61
| | | | | | | | | | Sidebar open/close state is now saved to a cookie (neko_sidebar) so it persists across page reloads. On first visit without a cookie, the sidebar defaults to closed on tablet and mobile (<=1024px viewport) and open on desktop. Removes the auto-open-on-resize behavior that was overriding user preference. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Merge pull request #5 from adammathes/claude/thicket-ready-crank-RmQuIAdam Mathes9 days7-5/+15
|\ | | | | Change mark-as-read threshold from 50% to 100% visibility
| * v3 ui: require 100% visibility before marking items as readClaude9 days7-5/+15
|/ | | | | | | | | | | | | Change IntersectionObserver threshold from 0.5 to 1.0 so items are only marked as read when fully scrolled into view, reducing accidental mark-as-read during fast scrolling. Also fix unused Category import in perf test and add thicket config.json to repository so future agents can use thicket CLI commands. Closes NK-s2g59a https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
* ticket priority changesAdam Mathes9 days1-2/+2
|
* V3 UI Polish: Improved keyboard navigation, fixed logo position, and updated ↵Adam Mathes9 days14-54/+115
| | | | | | | | | | | branding - Fix V3 keyboard navigation delay (resolved NK-wjats7) - Update V3 document title to 'neko' (resolved NK-4p3s91) - Fix V3 neko logo/button position to be top-left fixed (resolved NK-89za3s) - Improve FeedItems (React) stability with ref-based index tracking and robust tests - Sync V3 styling and selection feedback with V2 patterns - Rebuild production assets
* Fix v3ui: neko button fixed positionAdam Mathes9 days8-25/+10
| | | | | | | - Remove duplicate neko logo from v3 sidebar - Keep sidebar toggle button fixed at top-left even when sidebar is open - Add top padding to v3 sidebar to prevent overlap with the fixed toggle button - Update v3 tests to match UI changes
* Merge pull request #4 from adammathes/claude/performance-stress-testing-qQuV8Adam Mathes9 days8-1/+1024
|\ | | | | Add performance benchmarks, stress tests, and frontend perf tests
| * Add performance benchmarks, stress tests, and frontend perf testsClaude9 days8-1/+1024
| | | | | | | | | | | | | | | | | | | | | | | | Go benchmarks cover item CRUD/filter/sanitization, API endpoints (stream, item update, feed list), middleware stack (gzip, security headers, CSRF), and crawler pipeline (feed parsing, mocked crawl). Stress tests verify concurrent reads/writes and large dataset handling. Frontend perf tests measure template generation, DOM insertion, and store event throughput. New Makefile targets: bench, bench-short, stress, test-perf. https://claude.ai/code/session_01ChDVWFDrQoFjMYHpaLGr9s
* | Merge pull request #3 from adammathes/claude/performance-stress-testing-qQuV8Adam Mathes9 days2-0/+286
|\| | | | | Add performance and stress test plan