| Commit message (Collapse) | Author | Age | Files | Lines |
| | |
|
| | |
|
| |
|
|
| |
across all themes
|
| | |
|
| | |
|
| |
|
|
| |
https://claude.ai/code/session_0187FXrbScDSWfbNEk9SfJaj
|
| |
|
|
| |
https://claude.ai/code/session_0187FXrbScDSWfbNEk9SfJaj
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Rewrites the image proxy handler to address several issues:
- Stream responses with io.Copy instead of buffering entire image in memory
- Add 25MB size limit via io.LimitReader to prevent memory exhaustion
- Close resp.Body (was previously leaked on every request)
- Validate Content-Type is an image, rejecting HTML/JS/etc
- Forward Content-Type and Content-Length from upstream
- Use http.NewRequestWithContext to propagate client cancellation
- Check upstream status codes, returning 502 for non-2xx
- Fix ETag: use proper quoted format, remove bogus Etag request header check
- Increase timeout from 5s to 30s for slow image servers
- Use proper HTTP status codes (400 for bad input, 502 for upstream errors)
- Add Cache-Control max-age directive alongside Expires header
Tests: comprehensive coverage for Content-Type filtering, upstream errors,
streaming, ETag validation, User-Agent forwarding, and Content-Length.
Benchmarks: cache hit path and streaming at 1KB/64KB/1MB/5MB sizes.
https://claude.ai/code/session_01CZcDDVmF6wNs2YjdhvCppy
|
| |\
| |
| | |
Add comprehensive test coverage for security and import features
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Major coverage improvements:
- safehttp: 46.7% -> 93.3% (SafeDialer, redirect checking, SSRF protection)
- api: 81.8% -> 96.4% (HandleImport 0% -> 100%, stream errors, content types)
- importer: 85.3% -> 94.7% (ImportFeeds dispatcher, OPML nesting, edge cases)
- cmd/neko: 77.1% -> 85.4% (purge, secure-cookies, minutes, allow-local flags)
New tests added:
- Security regression tests (CSRF token uniqueness, mismatch rejection,
auth cookie HttpOnly, security headers, API auth requirements)
- Stress tests for concurrent mixed operations and rapid state toggling
- SSRF protection tests for SafeDialer hostname resolution and redirect paths
https://claude.ai/code/session_01XUBh32rHpbYue1JYXSH64Q
|
| |/
|
|
|
|
|
|
|
|
|
|
| |
Split light/dark into ☀ ☽ buttons above a horizontal rule, with
the 5 style emoji below. Increases icon size from 0.8rem to 1rem.
Replaces opacity-only approach with explicit rgba(0,0,0) color in dark
mode (sidebar remains grey in dark theme, so icons need dark ink).
Switches hover/active backgrounds to neutral rgba(128,128,128) so
they work correctly across all themes and modes.
https://claude.ai/code/session_01Jv3c8GdaDQMm5WYwHUJMVe
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
| |
Swap the single cycle button for individual emoji per theme:
○ Default, ◆ Refined, ▮ Terminal, ❧ Codex, ❀ Sakura.
Active theme gets a highlighted state. Separated from the
light/dark toggle with a thin divider.
https://claude.ai/code/session_01Jv3c8GdaDQMm5WYwHUJMVe
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Refined: softer dark-mode link color (#a0c4e8), fix export button
vertical alignment with inline-flex, tighten settings page spacing
(reduce gaps from 3rem to 1.5rem).
Terminal: switch accent from cyan to green (#4ae54a dark / #1a7a2e
light), add proper light mode with pale steel background, scanlines
only in dark mode.
Sidebar: add quick-access controls in footer — moon/sun icon toggles
light/dark, circle icon cycles through style themes showing current
name. Both update reactively on state change.
Add THEMES.md with full documentation on creating new themes:
variable reference, selector guide, light/dark mode tips, and the
registration process.
https://claude.ai/code/session_01Jv3c8GdaDQMm5WYwHUJMVe
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds a style theme system that layers additional CSS files on top of the
base stylesheet. Themes are loaded/unloaded dynamically via <link> tags.
- Default: existing look, unchanged
- Refined: typographic rhythm fixes, consistent spacing on settings page
- Terminal: monospace, dark phosphor CRT aesthetic (scanlines, cyan glow)
- Codex: book/Tufte-inspired with warm paper tones, serif type, fleurons
- Sakura: Japanese-inspired calm aesthetic (named for neko = cat)
Each theme supports both light and dark mode. Style selection persists
in localStorage and is independent of the light/dark toggle.
https://claude.ai/code/session_01Jv3c8GdaDQMm5WYwHUJMVe
|
| | |
|
| |
|
|
| |
headers and body, update monospace stack, and soft-deprecate tags
|
| | |
|
| | |
|
| |
|
|
| |
dividers
|
| |
|
|
| |
simplify Feed list to rows
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When the sidebar was changed to position:fixed (overlay mode), flex:1
was removed from .main-content. Without flex:1 or an explicit height,
.main-content relied on align-items:stretch for its height constraint.
This is unreliable for establishing a definite height that overflow-y:auto
respects — the element can grow with its content instead of constraining
at 100vh and scrolling.
Add height:100% to .main-content so it has a definite height from the
parent chain (body 100vh → #app 100% → .layout 100% → .main-content 100%).
This ensures overflow-y:auto creates a proper scroll container, which is
required for both the scroll-based infinite loading and mark-as-read to work.
https://claude.ai/code/session_01DpWhB9uGGMBnzqS28HxnuV
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
| |
Source changes since last dist commit shifted Vite content hashes.
Rebuilding ensures web/dist/v3/ matches a fresh `make ui-vanilla`.
|
| | |
|
| |
|
|
| |
Vanilla JS (V3)
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
| |
- 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
|
| |
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
| |
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>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
| |
- 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
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
|
|
|
|
|
| |
stability
- Sync v3 dark/light theme colors with v2 defaults
- Fix v3 settings input/select contrast in dark mode
- Add logo emoji to v3 sidebar
- Fix duplicate key warnings and side-effect issues in FeedItems.tsx (v2)
- Rebuild production assets
|
| |
|
|
|
|
|
| |
- Update Makefile to correctly build and copy frontend-vanilla (v3) assets
- Fix frontend-vanilla/vite.config.ts to build to its own dist directory
- Normalize CSRF check path and exclude /api/logout to fix v3 session clearing
- Include latest built assets for v3
|
| |
|
|
|
|
|
|
| |
- Close NK-oqd24q: Fix login access for v3/api
- Update web.go to exclude /login/ from CSRF check during initial submission
- Modernize web/static/login.html with new CSS and structure
- Add web/login_test.go to verify CSRF exclusion
- Created NK-ngokc3 for further CSRF enhancements
|
| | |
|
| |
|
|
| |
overflow, cleaned up styles
|
| |
|
|
| |
implement feed deselect, and complete Settings (Add Feed, Export/Import OPML)
|
| | |
|
| | |
|