[security] Mitigate SSRF in Image Proxy and Feed Fetcher

Restrict outbound HTTP requests to prevent access to internal networks. 1. Create a custom http.Transport for the fetcher clients. 2. In the DialContext, resolve the IP address of the target hostname. 3. Block connections to private IP ranges (RFC 1918) and loopback addresses (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16). 4. Disable following redirects to private IPs.


Implement Frontend Logout

Add logout button/link in dashboard and call /api/logout.


Add documentation for background crawler behavior

Document how the background crawler works in README.md: explain the --minutes flag, default behavior (60 minutes), how to disable background crawling (set to 0 or omit flag), and manual crawling with --update flag.


Implement Frontend Settings

Create settings page for managing feeds/categories.


docker compose fails

When running docker compose up I got the following error:
[2/3] STEP 1/9: FROM golang:1.23-bullseye AS backend-builder
Resolved "golang" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/golang:1.23-bullseye...
Getting image source signatures
Copying blob sha256:bb30cea4afcbc0a0405508119c28d87afb4518e3558e2f1fb0a52a0498994287
Copying blob sha256:a9acb5a6634ff8f020bd4562c483cdd83503103d2c080d87e777643b57123e41
Copying blob sha256:b26972d9a448e4dba0ac85216372d6ee52bc89839590b4e97f94b77ced5571fe
Copying blob sha256:b1efd17e5717172aa4463c9c599bce51a6939b602dbb135bf6c26d672a6e7496
Copying blob sha256:6a887974b056452b76229e3392cbf8513e741cd3dcd1f05e7397eea6fce361a0
Copying blob sha256:382d65ac76ebcbc7ba7ee0d232ae7afbec48e2b3b673983ac8ced522dabe3abb
Copying blob sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1
Copying config sha256:6f1643fb9acc4fc0b9bf95efd1b4b1cd274dcd73a39cc99ef57da203d7088f42
Writing manifest to image destination
[2/3] STEP 2/9: RUN go install github.com/GeertJohan/go.rice/rice@latest
go: downloading github.com/GeertJohan/go.rice v1.0.3
go: downloading github.com/GeertJohan/go.incremental v1.0.0
go: downloading github.com/akavel/rsrc v0.8.0
go: downloading github.com/daaku/go.zipexe v1.0.2
go: downloading github.com/jessevdk/go-flags v1.4.0
go: downloading github.com/nkovacs/streamquote v1.0.0
go: downloading github.com/valyala/fasttemplate v1.0.1
go: downloading github.com/valyala/bytebufferpool v1.0.0
--> 181d1254149e
[2/3] STEP 3/9: WORKDIR /app
--> 3f497307e2ca
[2/3] STEP 4/9: COPY go.mod go.sum ./
--> 339c24ca12cd
[2/3] STEP 5/9: RUN go mod download
go: go.mod requires go >= 1.24.2 (running go 1.23.12; GOTOOLCHAIN=local)
Error: building at STEP "RUN go mod download": while running runtime: exit status 1


refactor backend to have a clean API

create a nice clean API for the backend GO code that is more independent of the frontend

ensure that it is working with good tests


Increase Test Coverage to >80%

Project-wide test coverage is currently ~63%. Key gaps are in the new  and  packages, as well as some core model logic. Increase coverage to at least 80% to ensure stability.


Mobile Layout Verification for New Frontend

Verify and adjust the new fixed-width layout for mobile devices to ensure responsiveness.


delete vanilla js prototype

remove it, let's just focus on the react version. make sure everything still builds cleanly, etc after removing. remove any old tests for it, etc.


Prototype Vanilla JS Frontend


Vanilla JS: Implement Search

Add search bar to vanilla JS prototype and hook up to search API.


v2 frontend move the star to the RIGHT of the title

Look at the old implementation and make it look more like that! Big start, same size as the article title.


go vet fails on github ci

Looks like the newly enabled github ci runs go vet and got a bunch of errors including:

go vet ./...
  shell: /usr/bin/bash -e {0}
Error: config/config.go:6:2: missing go.sum entry for module providing package gopkg.in/yaml.v2 (imported by adammathes.com/neko/config); to add:
    go get adammathes.com/neko/config
Error: models/db.go:10:2: missing go.sum entry for module providing package github.com/mattn/go-sqlite3 (imported by adammathes.com/neko/models); to add:
    go get adammathes.com/neko/models
Error: models/feed/feed.go:10:2: missing go.sum entry for module providing package github.com/PuerkitoBio/goquery (imported by adammathes.com/neko/models/feed); to add:
    go get adammathes.com/neko/models/feed
Error: models/item/item.go:12:2: missing go.sum entry for module providing package github.com/advancedlogic/GoOse (imported by adammathes.com/neko/models/item); to add:
    go get adammathes.com/neko/models/item
Error: models/item/item.go:13:2: missing go.sum entry for module providing package github.com/microcosm-cc/bluemonday (imported by adammathes.com/neko/models/item); to add:
    go get adammathes.com/neko/models/item
Error: models/item/item.go:14:2: missing go.sum entry for module providing package github.com/russross/blackfriday (imported by adammathes.com/neko/models/item); to add:
    go get adammathes.com/neko/models/item
Error: crawler/crawler.go:7:2: missing go.sum entry for module providing package github.com/mmcdole/gofeed (imported by adammathes.com/neko/crawler); to add:
    go get adammathes.com/neko/crawler
Error: tui/tui.go:9:2: missing go.sum entry for module providing package github.com/charmbracelet/bubbles/list (imported by adammathes.com/neko/tui); to add:
    go get adammathes.com/neko/tui
Error: tui/tui.go:10:2: missing go.sum entry for module providing package github.com/charmbracelet/bubbles/viewport (imported by adammathes.com/neko/tui); to add:
    go get adammathes.com/neko/tui
Error: tui/tui.go:11:2: missing go.sum entry for module providing package github.com/charmbracelet/bubbletea (imported by adammathes.com/neko/tui); to add:
    go get adammathes.com/neko/tui
Error: tui/style.go:3:8: missing go.sum entry for module providing package github.com/charmbracelet/lipgloss (imported by adammathes.com/neko/tui); to add:
    go get adammathes.com/neko/tui
Error: web/web.go:19:2: missing go.sum entry for module providing package github.com/GeertJohan/go.rice (imported by adammathes.com/neko/web); to add:
    go get adammathes.com/neko/web
Error: web/rice-box.go:7:2: missing go.sum entry for module providing package github.com/GeertJohan/go.rice/embedded (imported by adammathes.com/neko/web); to add:
    go get adammathes.com/neko/web
Error: web/web.go:20:2: missing go.sum entry for module providing package golang.org/x/crypto/bcrypt (imported by adammathes.com/neko/web); to add:
    go get adammathes.com/neko/web
Error: main.go:16:2: missing go.sum entry for module providing package github.com/ogier/pflag (imported by adammathes.com/neko); to add:
    go get adammathes.com/neko
Error: Process completed with exit code 1.


fix font theming

The font selector should adjust more than just the titles/ui, the font stack should include the "normal" article text too, right now it's palatino in every stack, it should really just be the first one I think.


Implement Feed Items View

Create a component to display items for a selected feed. Fetch items from /api/stream?feed_id=...


v2 ui - collapsible feed list

In the left side navigation list of feeds, the feeds should be hidden by default. The word "feeds" should be a toggle to show/hide the list, with a triangle that indicates state.


Implement Mocked-API UI Tests

Configure Playwright to intercept /api/ requests and return mock JSON. This decouples UI testing from the backend, reducing VM crash risk and enabling fast UI iteration.


last item behavior on mobile

I think there's a bug where if the last item on screen on mobile isn't "big" enough it won't trigger loading more items, but not sure. please verify the behavior.


Create api/reader package and middleware


Implement Frontend Logout

Add logout button to dashboard header. Call /api/logout (need to create this potentially?). Redirect to /login


Infinite scroll

a key feature of the original version that when you scroll to the bottom, it catches that and loads more (based on the current filters, etc)


Vanilla JS: Mobile Layout

Make vanilla JS prototype responsive for mobile devices.


v2 frontend BLUE LINKS

Make most of the links BLUE and BOLD like in the old legacy version. Thanks


Vanilla JS: Implement Pagination

Implement 'Load More' or infinite scroll for item list in vanilla JS prototype.


Refactor HTTP-dependent functions for testability

Several functions use http.Get or external libraries directly (GetFullContent uses goose, ResolveFeedURL uses http.Get + goquery, imageProxyHandler uses http.Client). Refactor these to accept interfaces for HTTP fetching so they can be unit tested with mocks. This is the primary blocker for reaching 90% coverage.


Vanilla JS (v3): Tags, Filters, and Paging


sidebar still ugly

still very ugly, even compared to the original v1 static version

either make it nicer or just copy the v1 version more directly


Fix TUI Content View Navigation and Interaction

The TUI content view (reading a single item) is currently non-functional or severely limited. Users cannot easily navigate back, scroll, or interact with the content. This task involves improving the 'viewContent' state in the TUI.


Freeing up space by purging very old items

I have been running neko for so long that my production database is 1.4GB. Come up with a tool (ok to run it from command line) that purges some super old feed items to save space. Probably needs some variables on age, etc. Think carefully about the algorithm! it should be accessible from the CLI to start, although maybe we should show "db size" in settings too with an option to clean up.


[security] Add HTTP Security Headers

Add middleware to set standard security headers: Content-Security-Policy (restrict sources), X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: strict-origin-when-cross-origin.


Enhance UI with better loading indicators and error states

The application should have a consistent and premium feel for loading and error states. Currently, it uses simple text. We should implement skeleton screens or more polished animations.


Clean up unused font CSS variables

The font CSS variables might have duplicates or unused entries after the fix. Audit them.


scrape full text button

add this feature back in to the v2 ui and verify it is still working (not sure if we have any tests)


v2 frontend: when selected, don't change style of feed items

Just leave them the same when j/k "selects" an item. No blue side thing, no change in background, it's distracting. Just scroll it to the right place.


page size and performance

Do some analysis of page size (css/html/javascript) on the legacy version vs. new version and give me a report. We want it to be small and fast! If the new version is much worse file some tickets to investigate further.


Add configurable username support

Currently login accepts a username field but ignores it. We should allow configuring a username (defaulting to 'neko') and validate it during login.


Implement Frontend Login

Create login page and auth logic in the new React frontend. Port functionality from legacy login.html.


v2 ui - font size 18px

Compare your font sizes with the legacy version -- I think they're a little too small (16 vs 18 baseline)


font styles

Switch the default font stack and size to match the legacy UI


coverage status

check coverage status -- are we still close to 80%
it's ok to ignore the old static legacy javascript or vanilla js prototype
if it's low file a ticket to get coverage back up


Update golangci-lint version and config to v2

The local environment uses golangci-lint v2.9.0 which is incompatible with the current v1 config. Running migration updated the .golangci.yml to version 2. We should update the GitHub CI workflow to use a compatible version and ensure local/CI parity.


update Makefile

Ensure the Makefile builds things and works
Test it by running it regularly before checking in!


drop "mark read" button

there's no mark read/unread buttons, it's just by scrolling!


clean up root directory of project

There are some scripts in the root directory like run_e2e.sh that probably should be in a subdirectory -- look into it and make things a little tidier where approopriate.


Add crawl status indicator to UI

Currently triggering a crawl via 'Crawl All Feeds Now' just shows an alert. We should provide a visual status indicator and refresh the item list automatically when done.


Create 'make check' unified workflow

Create a 'make check' target that runs 'golangci-lint' (replacing 'go vet') and all unit tests (Backend + Frontend). This becomes the fast (<30s) 'Golden Command' for local verification.


Install golangci-lint in dev environment

Local Makefile uses 'go vet' because 'golangci-lint' is missing. CI uses golangci-lint. We should install it locally for consistency.


terminal UI

once there is good test coverage and a clean backend API, work on a nice efficient TUI with https://github.com/charmbracelet/bubbletea


Vanilla JS: Add Feed UI

Add UI to add a new feed by URL in vanilla JS prototype.


reach parity between vanilla js and react v2 ui

Continue implementing the vanilla js one with minimal overhad/depdnencies to be fast and lean. Make sure there are tests and rely on the v2 ui and legacy version as references.


Refactor E2E tests to use page objects

The E2E tests are getting complex. Refactor them to use the Page Object Model pattern for better maintainability.


Persist sidebar state across reloads

Currently sidebar state resets on reload. It should persist in localStorage like the theme.


Vanilla JS Parity: Read/Star/Filter

Implement read/unread toggle, star/unstar, and special filters (All, Unread, Starred) in vanilla JS prototype.


Create Python Compliance Suite


v2 ui: change title fonts to Helvetica Neue

to match style in legacy change font to match Helventic Neue where applicable


v2 ui: themes

simplify the themes selector by getting of the giant THEMES title

loook at the logic for the theme colors, it doesn't look like the feed item text is changing right. look at the legacy one for behavior.

Let's also simplify down to just light and dark themes (white bg, black bg) and use an emoji or something to distinguish.


v2 ui: sidebar design

I don't like the new sidebar design in v2 compared to v1. although I realize the v1 is kind of dated. can you take another pass at it -- more like v1, but you can spice it up a little bit maybe. but remember, this is a minimalist, simple, fast rss reader.


Make feed crawling async in API

Currently, POST /api/feed triggers an immediate crawl which blocks the response (or at least keeps the goroutine alive). Refactor the crawling architecture to be truly async with a job queue or status updates, improving API responsiveness and reliability.


Implement Item Interactions

Add ability to toggle read/unread and star/unstar status for items. Use PUT /item/:id


check coverage again

check test coverage again and see if more tests are needed


setup github ci

Maybe it'd be nice to have github run the tests. Is that a thing we can try to setup


UI: Improve accessibility for star icon

The new star button should have proper aria-labels and potentially better focus states for screen readers.


UI Styling: Dark Mode Support


stress test with a REALLY big database

I have been using a version of neko for over a decade and my prod database is 1.4GB sqlite file. it's in big_neko.db

run some tests with that big database and see if anything messes up! DO NOT CHECK IN THAT BIG DATABASE EVER.

if there are bugs or performance issues with such a big db, file some tickets for us to evaluate and we can create some synthetic data or issues later on.


v2 ui - title styling

The title of the article stays blue and bold regardless of read state.


github CI fails

Both the backend and frontend failed the CI jobs failed the lint checks.

are we running those properly locally before submitting

also the frontent consistency check failed


write tests based on closed CLs

Look at the recent CLs and closed tickets over the past 48 hours and identify areas where we need regression tests or other tests and write tickets for them as additional testing


Style Settings page to match Glass sidebar

The settings page currently uses the old retro aesthetic. It should be updated to match the new minimalist 'glass' sidebar style for visual consistency. This should include updating form elements, backgrounds, and typography.


Improve mobile responsiveness of React UI

The React UI should be fully responsive and work well on small screens. Now that the vanilla JS prototype is removed, we should ensure the main interface is a great experience for mobile users.


TUI is terrible and needs fixing

The TUI doesn't really work and doesn't make sense. Think very hard and look at the v2 HTML UI implementation and make something cool like that. Probably needs tests too.


[security] Implement CSRF Protection for API

Add CSRF protection to all state-changing API endpoints. 1. Implement a middleware that generates a CSRF token and sets it in a cookie (readable by JS) or header. 2. Update the AuthWrap middleware to validate the presence of this token in the X-CSRF-Token header for all unsafe methods (POST, PUT, DELETE). 3. Update the React frontend to read the token and include it in all API requests.


Add coverage check to 'make check'

Add a code coverage check to the 'make check' workflow, ensuring it doesn't significantly slow down execution. This replaces ad-hoc coverage checks.


FEEDS in sidebar needs to be more clearly a collapsible thing

FEEDS in the sidebar needs a caret (> that turns to V) or something similar to make it clear it's a toggle collapsible list thing


Feed list collapsed by default

The list of feeds on the left side should be collapsed by default, with a little control to extend it.


Remaining test coverage gaps

Cross-package test coverage is at 81.2%. The remaining untested functions are: GetFullContent (goose HTTP extraction), indexHandler/serveBoxedFile (rice.MustFindBox), Serve (starts HTTP server), main, util.init. To reach 90%, consider: (1) refactoring GetFullContent to accept an interface for HTTP fetching, (2) refactoring Serve to extract route setup into a testable function, (3) mocking rice.MustFindBox, (4) using feeds from https://trenchant.org/feeds.txt as static test fixtures for integration tests.


Add Local Git Hooks

Create a script/make target to install a pre-push hook that runs 'make check'. This enforces quality gates locally, keeping the CI clean.


Investigate E2E Tag View flakiness

The E2E test for /v2/tag/Tech was temporarily disabled because it was timing out/failing. Investigate if it's a race condition or a routing issue.


Vanilla JS: Implement Test Infrastructure

Setup testing infrastructure for vanilla JS prototype to ensure 80% coverage. Refactor app.js for testability and add unit tests.


Vanilla JS (v3): Settings, Search, and Keyboard Shortcuts


URLs in UI are api/feed output, not loadable HTML

After clicking in the sidebar, you get to a URL like http://localhost:9001/feed/38?filter=all but if you hit "reload" in the browser that retuns a blob of JSON to the browser! Oops. Maybe just don't change the user visible URL at all. If we do change the URLs, maybe just use #/feed/38/filter=all or something similar that is just client side for the JS.


[ui] when a left menu item is "active" make it bold

The "default" is UNREAD - this should be in the "bold" state when you're seeing that. When you filter out to "ALL" that should instead be bold. Same with the individual feeds if one is selected. And Starred.


infinite scroll on ipad/mobile

On a mobile device, the infinite scrooll didn't seem to be working properly and triggering as I scrolled to the bottom. Are the right triggers set up for mobile browsers as well as desktop -- this was on an ipad.


Improve scraper heuristics

The scraper currently uses a simple fallback between CleanedText and TopNode. It could be improved to better handle different article layouts.


600px width by default, closer to left panel

On desktop the feed items are too narrow (~500px) compared to legacy version which is ~600px.


adding feed in v2 ui shows error

added https://trenchant.org/rss.xml as a feed in the UI but it gave some weird message inline like unexpected character, but it did eventually add it. what happened there


add neko cat back to hide left navivation

Change the "neko reader" to the cat emoji like in the legacy and have it toggle visibility of the left nav


Fix Playwright E2E Tests

The e2e tests in tests/e2e.spec.ts are failing when run with vitest. They should be run with playwright test runner, or configured correctly. Currently excluded from vitest.


Evaluate E2E test harness

Evaluate the current E2E test harness (Cleaning up test environment...
Cleanup complete.
Building backend...
Creating data directory...
Starting mock feed server on port 9090...
Mock Server PID: 166494
Mock server is up.
Starting backend on port 4994...
Backend PID: 166520
Waiting for backend to start...
Waiting...
Backend is up!
Running E2E tests...

> frontend@0.0.0 test:e2e
> playwright test

Running 13 tests using 1 worker

[1/13] [chromium] › tests/auth.spec.ts:12:5 › Authentication - No Password Required › should allow direct access to dashboard without login
[2/13] [chromium] › tests/auth.spec.ts:25:5 › Authentication - No Password Required › should allow login with empty password
[3/13] [chromium] › tests/auth.spec.ts:38:5 › Authentication - No Password Required › should report authenticated status via API when no password
[4/13] [chromium] › tests/auth.spec.ts:53:10 › Authentication - Password Required › should redirect to login when accessing protected routes
[5/13] [chromium] › tests/auth.spec.ts:64:10 › Authentication - Password Required › should reject incorrect password
[6/13] [chromium] › tests/auth.spec.ts:79:10 › Authentication - Password Required › should accept correct password and redirect to dashboard
[7/13] [chromium] › tests/auth.spec.ts:93:10 › Authentication - Password Required › should persist authentication across page reloads
[8/13] [chromium] › tests/auth.spec.ts:109:10 › Authentication - Password Required › should logout and redirect to login page
[9/13] [chromium] › tests/auth.spec.ts:128:10 › Authentication - Password Required › should report unauthenticated status via API
[10/13] [chromium] › tests/auth.spec.ts:142:5 › Authentication - Complete Flow › should handle complete user flow without password
[11/13] [chromium] › tests/crawl.spec.ts:4:5 › Crawl Integration › should add a feed and see items after crawl
[12/13] [chromium] › tests/e2e.spec.ts:4:3 › Neko Reader E2E › should allow login, viewing feeds, and logout
[chromium] › tests/e2e.spec.ts:4:3 › Neko Reader E2E › should allow login, viewing feeds, and logout
Step 5: Navigate to Home

Step 6: Logout

[13/13] [chromium] › tests/font.spec.ts:4:5 › Font Theme Settings › should change font family when theme starts
  6 skipped
  7 passed (5.2s)

To open last HTML report run:

  npx playwright show-report

Tests passed!
Cleaning up...
Cleaning up test environment...
Cleanup complete.) which is brittle and resource intensive. Consider alternative approaches or refactoring.


[feature] light/dark/black toggle

Add in a simple [light | dark | black] theme toggler like in the legacy version.


docker support

add support so people can self-host this in docker and (maybe) test it yourself. maybe keep it in a docker directory with separate docs etc.


enhance github ci/cq

Make sure we have the right CI/CQ things in the github workflow. Can it test our docker compose for us too maybe


UI Styling: Global Typography & Layout (Fixed Width)


Re-enable and fix errcheck lints

Re-enable 'errcheck' in .golangci.yml and fix the remaining ~140 issues, mostly related to unchecked Writes and DB operations.


Fix and Re-enable Playwright E2E Tests

E2E tests were crashing the VM and timing out. Disabled them in package.json. Need to investigate resource usage and re-enable.


v2 ui bug - panel open by default

Panel is closed by default, it should be open by default on desktop.


serve "legacy" version UI at /v1/ instead of /

Let's "softly" start to deprecated the legacy version by moving it to /v1/ -- ideally this won't require any changes but there may be some relative/absolute URLs to adjust in the static files there or in rouoting


Mock RSS feeds in E2E tests

Currently E2E tests fetch real feeds like CNN, which makes them slow (10s+) and potentially flaky depending on network. Use a local mock server or file-based mocks.


Implement Tag View

Create frontend view for browsing items by tag/category. Use /tag/:id endpoint.


Fix TypeScript Lint Errors in Tests

There are lint errors in test files regarding jest-dom matchers (toBeInTheDocument, etc). Ensure proper types are included.


fix github ci

seems to be broken, are the right things still in there given all the refactorings


[security] Run Docker Container as Non-Root User

Update the Dockerfile to create and use a non-privileged user. 1. Create a user (e.g., neko) in the final stage. 2. Ensure the /app/data directory is owned by this user. 3. Switch to this user using USER neko before the CMD.


UI: Add skeleton loaders for feed item loading

The currently 'Loading more...' text is basic. We should add skeleton loaders for a smoother infinite scroll experience.


Benchmark 'make check' execution time

Measure the execution time of the 'make check' workflow to ensure it remains fast and doesn't hinder developer velocity.


Ensure 80% Frontend Test Coverage

Configure coverage reporting in vitest and ensure the frontend codebase maintains at least 80% test coverage.


Multi-select feeds in sidebar

Enable multi-selection of feeds in the sidebar to view combined streams from several feeds at once. Keep current additive filtering logic.


make new v2 UI the default and serve at /

After we move the old UI to be served at v1, serve the new UI at /

We can keep serving it at v2/ as well if we want.


Implement ClientLogin and Token endpoints


Implement Stream Contents endpoint


get rid of the "selected" highlight thing

the legacy version doesn't do that and i find it distracting, j/k just move things up/down


Crawler testing

The general usage of neko is to run it and have it crawl feeds in the background after X minutes

Do we have a test that can verify that's happening


UI Styling: Controls & Header


Implement Subscription List and UserInfo endpoints


username + password

it's too weird to have just a password -- in the old UI i had a username but it was just ignored. but password managers get confused by this new no username thing.

let's make it so you can enter a username and password. to start, just let that be a no-op (it ignores the username and just pays attention to the password.)

we can consider later on if we want to make the username real and definable too.


import/export

Import/Export has only ever been partially implemented. Let's finish it up across OPML (de facto standard) but also simple txt line oriented input/output. We may need to file a ticket to deal with the async crawling as part of this.


filtiering behavior between all/unread/starred + feeds

reopening as this still seems to be broken!

veryify by clicking "all" then a a feed -- it only shows unread items in that feed, not "all" and the URLs seem to not include the param

The filters are additive, but the UI isn't working that way right now.

always one of these is selected
-
Unread -- filters the list to only unread items
All -- no filter applied, shows read+unread
Starred -- filters to everything starred, regardless of read state. Since you can't star things without reading them!

FEEDS
by default *none* are selected, so there is no filtering
Once one is selected, that filter is applied but it's additive -- if you are in `all` it shows `all` but filtered to that feed. Both are bolded. If youo click `unread` it would just show unread in that feed.

This is a bit tricky, you can look at the old UI implementation to see some logic that reflects this. We may want some tests too to catch this bug next time!

Nice to have: be able to multi-select feeds (that wasn't possible in the old version) but that can be a follow-up ticket.


Add end-to-end integration test for complete crawl cycle

Create an integration test that verifies the complete crawl workflow: start server with background crawling enabled, add a feed via API, wait for background crawl to execute, verify items are fetched and stored. This would require mocking or using a test RSS feed and potentially adjusting timing for faster test execution.


Migrate frontend to /api/ endpoints

The backend now provides a clean REST API at /api/. Update the frontend UI to use these new endpoints instead of the legacy backward-compatibility routes (/stream/, /feed/, etc.). This will allow for cleaner separation and better utilization of proper REST patterns.


font themes

in the v2 ui, let's offer a few different font stacks the user can switch through. primarily this should just change font-face, maybe size, but don't worry about colors or anything right now.

the current default (helvetica neue, palatino)
a fancy all serif stack
a no-nonsense modern san-serif stack
a terminal inspired fixed width stack


titles changing on read state and hover

Titles are changing on read state from blue to grey. They should just stay blue all the time.

Titles are getting underlined on hover. They should have no underline regardless of hover state.


update documentation based on all the recent changes

update README.md based on what's been changed given all the CLs and tickets recently


add search to new ui


fix docker-compose

bug when trying to build in docker -- we may want to add an automated test for this later (though it may be hard since we're building in a vm to nest these)

--> 668e2e2c4b44
[2/3] STEP 3/9: WORKDIR /app
--> b42c7c265b7f
[2/3] STEP 4/9: COPY go.mod go.sum ./
--> 093e4d9b623e
[2/3] STEP 5/9: RUN go mod download
--> 208c8aaac5eb
[2/3] STEP 6/9: COPY . .
--> 7c44260c3ac0
[2/3] STEP 7/9: COPY --from=frontend-builder /app/frontend/dist ./frontend/dist
--> 09749e6660e1
[2/3] STEP 8/9: RUN rice -i ./web embed-go
2026/02/14 17:34:13 no calls to rice.FindBox() found
--> cdc88c64da36
[2/3] STEP 9/9: RUN go build -o neko .
no Go files in /app
Error: building at STEP "RUN go build -o neko .": while running runtime: exit status 1


Implement Export/Import UI

Add UI in settings to download OPML export and upload OPML import. Use /export/ and /import/ (need to check if import exists).


Enable Gzip Compression in Go Backend

Check if the Go backend is serving content with gzip compression. If not, implement it to reduce page size and improve performance. Add tests to verify.


new web frontend

The current frontend uses an old version of backbone and jquery. Let's "deprecate" it -- keep it arouond so we can test against it and use it, but let's be able to also serve and use a nice shiny new frontend written in either simiple, highly efficient vanilla javascript, or put together something in react or similar. Needs to feel fast and low latency!

It's very important that this new frontend has all the functionality of the existing one AND looks similar (use same style, etc, but adjust a little if needed.)

ALSO make it highly testable and have high test coverage as you go. I don't want it to use the Chrome browser plugin thing, just test it on your own using things from the command line you can do.


Wire Reader API into web.go


make sure the github CI jobs are included in the tests/jobs locally!


v2 ui - font size adjustments

Move font-size: 18px to :root so rem units resolve correctly. Adjust title size to ~24px.


E2E Testing

Set up E2E testing with Playwright or Cypress to verify full flows: Login -> View Feeds -> View Items -> Logout


security changes broke legacy

I think some of the security policies make it so the old legacy one doesn't work. this may just be WAI but have a look

[Warning] jQuery.Deferred exception: Refused to evaluate a string as JavaScript because 'unsafe-eval' or 'trusted-types-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'". (jquery-3.3.1.min.js, line 2)
 (2)
"Function@[native code]
o@http://localhost:4994/static/jquery.tmpl.min.js:10:3543
template@http://localhost:4994/static/jquery.tmpl.min.js:10:1914
tmpl@http://localhost:4994/static/jquery.tmpl.min.js:10:1422
render@http://localhost:4994/static/ui.js:208:23
nr@http://localhost:4994/static/underscore-1.13.1.min.js:6:7308
@http://localhost:4994/static/underscore-1.13.1.min.js:6:7733
@http://localhost:4994/static/underscore-1.13.1.min.js:6:786
boot@http://localhost:4994/static/ui.js:598:28
@http://localhost:4994/static/ui.js:8:9
l@http://localhost:4994/static/jquery-3.3.1.min.js:2:29380
@http://localhost:4994/static/jquery-3.3.1.min.js:2:29678"
undefined


Vanilla JS (v3): Basic Fetch and Feed List


Scaffold Vanilla JS Frontend (v3)


UI Styling: Feed Items (Spacing, Dateline)


https://computer.rip/rss.xml fails to importa

running neko -a https://computer.rip/rss.xml gave an error. debug it and add test case to catch.


consistency in sidebar

With the new sidebar styling, SETTINGS and LOGOUT and the light/dark look really different than the rest. Let's make them more consistent from a style perspective.


update README.md

Ensure the build, configuration, etc are up too date.
Note the git change when we started to vibe-code this in the history (with dates etc.)


Vanilla JS: Test Infrastructure & Coverage

Setup testing framework (likely vitest or simple runner) for vanilla JS. Refactor code for testability. Aim for 80% coverage on vanilla/app.js logic.


test coverage

assume the code works properly (it mostly does)
get to 90% test coverage on the go code


add "star" back in

rather than the word "star" it should just have a star that changes colors right next to the title


Fix backend linting issues reported by golangci-lint

golangci-lint reports 64 issues including 46 errcheck violations (ignored errors in web handlers), 13 staticcheck issues (e.g., using 307/401 literals instead of http constants), and minor formatting/unused param issues. These should be addressed to improve code quality.


slow scrolling in v2 ui compared to v1

When using j/k to go to the next feed, they appeared instantly, now it feels like a slow scroll. Make it speedy again.


UI Styling: Sidebar (Fixed, Gray Background)


Implement Frontend Feed List

Create feed list view in new frontend. Fetch feeds from API.


neko button always must be visible

once you hide the sidebar with the nekoo button, there's no way to unhide it in the v2 ui after the recent changes