diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-14 08:58:38 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-14 08:58:38 -0800 |
| commit | e3c379d069ffa9661561d25cdbf2f5894a2f8ee8 (patch) | |
| tree | 24d0e9f5610dd9c8f873c5b78e6bc1c88d32840a /.thicket/tickets.jsonl | |
| parent | 4b06155fbde91a1bef6361ef36efb28789861928 (diff) | |
| download | neko-e3c379d069ffa9661561d25cdbf2f5894a2f8ee8.tar.gz neko-e3c379d069ffa9661561d25cdbf2f5894a2f8ee8.tar.bz2 neko-e3c379d069ffa9661561d25cdbf2f5894a2f8ee8.zip | |
Refactor: project structure, implement dependency injection, and align v2 UI with v1
Diffstat (limited to '.thicket/tickets.jsonl')
| -rw-r--r-- | .thicket/tickets.jsonl | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/.thicket/tickets.jsonl b/.thicket/tickets.jsonl index 29ccb06..732d5d5 100644 --- a/.thicket/tickets.jsonl +++ b/.thicket/tickets.jsonl @@ -1,3 +1,4 @@ +{"id":"NK-0ca7nq","title":"[security] Mitigate SSRF in Image Proxy and Feed Fetcher","description":"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.","type":"","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-14T16:35:57.352011404Z","updated":"2026-02-14T16:36:49.362993079Z"} {"id":"NK-0nf7hu","title":"Implement Frontend Logout","description":"Add logout button/link in dashboard and call /api/logout.","type":"task","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T05:50:46.760744241Z","updated":"2026-02-13T15:28:14.486180285Z"} {"id":"NK-0ppv3f","title":"Implement Frontend Settings","description":"Create settings page for managing feeds/categories.","type":"task","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T05:44:01.631640578Z","updated":"2026-02-13T15:04:12.408401691Z"} {"id":"NK-13v159","title":"docker compose fails","description":"When running docker compose up I got the following error:\n[2/3] STEP 1/9: FROM golang:1.23-bullseye AS backend-builder\nResolved \"golang\" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)\nTrying to pull docker.io/library/golang:1.23-bullseye...\nGetting image source signatures\nCopying blob sha256:bb30cea4afcbc0a0405508119c28d87afb4518e3558e2f1fb0a52a0498994287\nCopying blob sha256:a9acb5a6634ff8f020bd4562c483cdd83503103d2c080d87e777643b57123e41\nCopying blob sha256:b26972d9a448e4dba0ac85216372d6ee52bc89839590b4e97f94b77ced5571fe\nCopying blob sha256:b1efd17e5717172aa4463c9c599bce51a6939b602dbb135bf6c26d672a6e7496\nCopying blob sha256:6a887974b056452b76229e3392cbf8513e741cd3dcd1f05e7397eea6fce361a0\nCopying blob sha256:382d65ac76ebcbc7ba7ee0d232ae7afbec48e2b3b673983ac8ced522dabe3abb\nCopying blob sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1\nCopying config sha256:6f1643fb9acc4fc0b9bf95efd1b4b1cd274dcd73a39cc99ef57da203d7088f42\nWriting manifest to image destination\n[2/3] STEP 2/9: RUN go install github.com/GeertJohan/go.rice/rice@latest\ngo: downloading github.com/GeertJohan/go.rice v1.0.3\ngo: downloading github.com/GeertJohan/go.incremental v1.0.0\ngo: downloading github.com/akavel/rsrc v0.8.0\ngo: downloading github.com/daaku/go.zipexe v1.0.2\ngo: downloading github.com/jessevdk/go-flags v1.4.0\ngo: downloading github.com/nkovacs/streamquote v1.0.0\ngo: downloading github.com/valyala/fasttemplate v1.0.1\ngo: downloading github.com/valyala/bytebufferpool v1.0.0\n--\u003e 181d1254149e\n[2/3] STEP 3/9: WORKDIR /app\n--\u003e 3f497307e2ca\n[2/3] STEP 4/9: COPY go.mod go.sum ./\n--\u003e 339c24ca12cd\n[2/3] STEP 5/9: RUN go mod download\ngo: go.mod requires go \u003e= 1.24.2 (running go 1.23.12; GOTOOLCHAIN=local)\nError: building at STEP \"RUN go mod download\": while running runtime: exit status 1","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T01:10:13.257269131Z","updated":"2026-02-14T01:15:05.19401879Z"} @@ -12,11 +13,12 @@ {"id":"NK-4juza2","title":"v2 ui - collapsible feed list","description":"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.","type":"feature","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T02:48:25.194856022Z","updated":"2026-02-14T03:16:19.259726648Z"} {"id":"NK-59kbij","title":"Implement Frontend Logout","description":"Add logout button to dashboard header. Call /api/logout (need to create this potentially?). Redirect to /login","type":"","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T14:58:18.343464645Z","updated":"2026-02-13T15:01:33.783216589Z"} {"id":"NK-5ocxgm","title":"Infinite scroll","description":"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)","type":"task","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-13T19:27:01.14879752Z","updated":"2026-02-13T19:45:02.283640203Z"} -{"id":"NK-5zgzee","title":"Vanilla JS: Mobile Layout","description":"Make vanilla JS prototype responsive for mobile devices.","type":"feature","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-14T04:47:42.972969683Z","updated":"2026-02-14T04:47:42.972969683Z"} +{"id":"NK-5zgzee","title":"Vanilla JS: Mobile Layout","description":"Make vanilla JS prototype responsive for mobile devices.","type":"feature","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-14T04:47:42.972969683Z","updated":"2026-02-14T04:47:42.972969683Z"} {"id":"NK-6b4a2e","title":"v2 frontend BLUE LINKS","description":"Make most of the links BLUE and BOLD like in the old legacy version. Thanks","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T00:44:47.147880845Z","updated":"2026-02-14T01:09:26.770086073Z"} -{"id":"NK-6o87rr","title":"Vanilla JS: Implement Pagination","description":"Implement 'Load More' or infinite scroll for item list in vanilla JS prototype.","type":"feature","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-14T04:47:40.618957267Z","updated":"2026-02-14T04:47:40.618957267Z"} +{"id":"NK-6o87rr","title":"Vanilla JS: Implement Pagination","description":"Implement 'Load More' or infinite scroll for item list in vanilla JS prototype.","type":"feature","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-14T04:47:40.618957267Z","updated":"2026-02-14T04:47:40.618957267Z"} {"id":"NK-6q9nyg","title":"Refactor HTTP-dependent functions for testability","description":"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.","type":"cleanup","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-13T03:54:37.630148644Z","updated":"2026-02-14T02:44:05.328784994Z"} {"id":"NK-7tzbql","title":"Fix TUI Content View Navigation and Interaction","description":"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.","type":"bug","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T05:02:57.382793121Z","updated":"2026-02-13T05:06:15.144485446Z"} +{"id":"NK-7xuajb","title":"[security] Add HTTP Security Headers","description":"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.","type":"","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-14T16:35:59.320775688Z","updated":"2026-02-14T16:36:49.446994841Z"} {"id":"NK-8rhpp3","title":"v2 frontend: when selected, don't change style of feed items","description":"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.","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T00:39:50.01934312Z","updated":"2026-02-14T01:02:54.204739756Z"} {"id":"NK-8s75ec","title":"page size and performance","description":"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.","type":"task","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-13T20:16:13.898081788Z","updated":"2026-02-13T21:50:12.004391671Z"} {"id":"NK-9hx0y7","title":"Implement Frontend Login","description":"Create login page and auth logic in the new React frontend. Port functionality from legacy login.html.","type":"","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T05:44:01.546395342Z","updated":"2026-02-13T05:50:33.877452063Z"} @@ -25,9 +27,11 @@ {"id":"NK-acq08a","title":"update Makefile","description":"Ensure the Makefile builds things and works\nTest it by running it regularly before checking in!","type":"task","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T00:55:40.127322076Z","updated":"2026-02-14T01:26:31.564799193Z"} {"id":"NK-ahzf5c","title":"drop \"mark read\" button","description":"there's no mark read/unread buttons, it's just by scrolling!","type":"task","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-13T19:28:20.708443259Z","updated":"2026-02-13T20:26:43.029168286Z"} {"id":"NK-bsdwqz","title":"terminal UI","description":"once there is good test coverage and a clean backend API, work on a nice efficient TUI with https://github.com/charmbracelet/bubbletea","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T01:54:02.285738454Z","updated":"2026-02-13T04:42:09.824268427Z"} -{"id":"NK-ca9t70","title":"Vanilla JS: Add Feed UI","description":"Add UI to add a new feed by URL in vanilla JS prototype.","type":"feature","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-14T04:47:41.764330544Z","updated":"2026-02-14T04:47:41.764330544Z"} -{"id":"NK-chns2b","title":"reach parity between vanilla js and react v2 ui","description":"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.","type":"epic","status":"open","priority":0,"labels":null,"assignee":"","created":"2026-02-14T04:45:06.813453353Z","updated":"2026-02-14T04:45:06.813453353Z"} +{"id":"NK-ca9t70","title":"Vanilla JS: Add Feed UI","description":"Add UI to add a new feed by URL in vanilla JS prototype.","type":"feature","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-14T04:47:41.764330544Z","updated":"2026-02-14T04:47:41.764330544Z"} +{"id":"NK-chns2b","title":"reach parity between vanilla js and react v2 ui","description":"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.","type":"epic","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T04:45:06.813453353Z","updated":"2026-02-14T04:45:06.813453353Z"} {"id":"NK-d4c8jv","title":"Vanilla JS Parity: Read/Star/Filter","description":"Implement read/unread toggle, star/unstar, and special filters (All, Unread, Starred) in vanilla JS prototype.","type":"feature","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T04:46:32.113504545Z","updated":"2026-02-14T04:47:46.412290355Z"} +{"id":"NK-doss0v","title":"v2 ui: change title fonts to Helvetica Neue","description":"to match style in legacy change font to match Helventic Neue where applicable","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T06:27:57.270935467Z","updated":"2026-02-14T06:31:42.798620609Z"} +{"id":"NK-dp5efo","title":"v2 ui: themes","description":"simplify the themes selector by getting of the giant THEMES title\n\nloook 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.","type":"task","status":"open","priority":0,"labels":null,"assignee":"","created":"2026-02-14T06:30:23.170098963Z","updated":"2026-02-14T06:30:23.170098963Z"} {"id":"NK-ed1iah","title":"Make feed crawling async in API","description":"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.","type":"cleanup","status":"icebox","priority":4,"labels":null,"assignee":"","created":"2026-02-13T04:26:55.908243985Z","updated":"2026-02-13T04:26:55.908243985Z"} {"id":"NK-ek0cox","title":"Implement Item Interactions","description":"Add ability to toggle read/unread and star/unstar status for items. Use PUT /item/:id","type":"","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T14:55:14.825454967Z","updated":"2026-02-13T14:58:18.307521003Z"} {"id":"NK-fkc119","title":"setup github ci","description":"Maybe it'd be nice to have github run the tests. Is that a thing we can try to setup","type":"feature","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T03:16:32.574415787Z","updated":"2026-02-14T03:23:01.837550873Z"} @@ -35,9 +39,10 @@ {"id":"NK-fnaohu","title":"UI Styling: Dark Mode Support","description":"","type":"","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T18:05:19.59504351Z","updated":"2026-02-13T18:11:46.326064329Z"} {"id":"NK-fpzx66","title":"v2 ui - title styling","description":"The title of the article stays blue and bold regardless of read state.","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T03:22:55.339956853Z","updated":"2026-02-14T03:28:01.555909701Z"} {"id":"NK-gdf99z","title":"TUI is terrible and needs fixing","description":"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.","type":"epic","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-14T03:51:59.882212859Z","updated":"2026-02-14T04:31:28.290051717Z"} +{"id":"NK-gfh33y","title":"[security] Implement CSRF Protection for API","description":"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.","type":"","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-14T16:35:56.341543505Z","updated":"2026-02-14T16:36:49.305429179Z"} {"id":"NK-gnxc6e","title":"Feed list collapsed by default","description":"The list of feeds on the left side should be collapsed by default, with a little control to extend it.","type":"feature","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T00:58:15.661695308Z","updated":"2026-02-14T01:29:12.82081713Z"} {"id":"NK-gqkh96","title":"Remaining test coverage gaps","description":"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.","type":"cleanup","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-13T03:54:30.298141982Z","updated":"2026-02-14T02:44:05.399097286Z"} -{"id":"NK-hspao2","title":"Vanilla JS: Implement Test Infrastructure","description":"Setup testing infrastructure for vanilla JS prototype to ensure 80% coverage. Refactor app.js for testability and add unit tests.","type":"task","status":"open","priority":1,"labels":null,"assignee":"","created":"2026-02-14T05:13:11.587767054Z","updated":"2026-02-14T05:13:11.587767054Z"} +{"id":"NK-hspao2","title":"Vanilla JS: Implement Test Infrastructure","description":"Setup testing infrastructure for vanilla JS prototype to ensure 80% coverage. Refactor app.js for testability and add unit tests.","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T05:13:11.587767054Z","updated":"2026-02-14T05:13:11.587767054Z"} {"id":"NK-hyej38","title":"[ui] when a left menu item is \"active\" make it bold","description":"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.","type":"epic","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-14T00:47:25.74838134Z","updated":"2026-02-14T01:25:07.267016355Z"} {"id":"NK-iw9l7h","title":"Improve scraper heuristics","description":"The scraper currently uses a simple fallback between CleanedText and TopNode. It could be improved to better handle different article layouts.","type":"feature","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-14T01:04:11.588135487Z","updated":"2026-02-14T01:04:11.588135487Z"} {"id":"NK-jhludy","title":"600px width by default, closer to left panel","description":"On desktop the feed items are too narrow (~500px) compared to legacy version which is ~600px.","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-13T20:14:48.84900972Z","updated":"2026-02-13T20:50:22.207833479Z"} @@ -49,12 +54,16 @@ {"id":"NK-lrew5z","title":"UI Styling: Global Typography \u0026 Layout (Fixed Width)","description":"","type":"","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T18:04:57.254341682Z","updated":"2026-02-13T18:11:31.436752093Z"} {"id":"NK-m8bya7","title":"Fix and Re-enable Playwright E2E Tests","description":"E2E tests were crashing the VM and timing out. Disabled them in package.json. Need to investigate resource usage and re-enable.","type":"bug","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-14T03:08:18.501189975Z","updated":"2026-02-14T04:00:03.995357386Z"} {"id":"NK-mbuw7q","title":"v2 ui bug - panel open by default","description":"Panel is closed by default, it should be open by default on desktop.","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T02:46:56.870671639Z","updated":"2026-02-14T03:08:17.322841854Z"} +{"id":"NK-mgmn5m","title":"serve \"legacy\" version UI at /v1/ instead of /","description":"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","type":"task","status":"open","priority":0,"labels":null,"assignee":"","created":"2026-02-14T16:41:04.710679944Z","updated":"2026-02-14T16:41:04.710679944Z"} {"id":"NK-mwf9q2","title":"Implement Tag View","description":"Create frontend view for browsing items by tag/category. Use /tag/:id endpoint.","type":"","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T15:04:12.441165286Z","updated":"2026-02-13T18:04:38.644796168Z"} {"id":"NK-n7nuyy","title":"Fix TypeScript Lint Errors in Tests","description":"There are lint errors in test files regarding jest-dom matchers (toBeInTheDocument, etc). Ensure proper types are included.","type":"bug","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-13T21:50:15.140702806Z","updated":"2026-02-13T21:50:15.140702806Z"} +{"id":"NK-o3n9jf","title":"[security] Run Docker Container as Non-Root User","description":"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.","type":"","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-14T16:35:58.328232962Z","updated":"2026-02-14T16:36:49.406727944Z"} {"id":"NK-ojdcmq","title":"UI: Add skeleton loaders for feed item loading","description":"The currently 'Loading more...' text is basic. We should add skeleton loaders for a smoother infinite scroll experience.","type":"task","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-13T19:45:07.376295295Z","updated":"2026-02-13T19:45:07.376295295Z"} {"id":"NK-op5594","title":"Ensure 80% Frontend Test Coverage","description":"Configure coverage reporting in vitest and ensure the frontend codebase maintains at least 80% test coverage.","type":"task","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T05:46:24.13314466Z","updated":"2026-02-13T05:50:46.728239299Z"} +{"id":"NK-p89hyt","title":"make new v2 UI the default and serve at /","description":"After we move the old UI to be served at v1, serve the new UI at /\n\nWe can keep serving it at v2/ as well if we want.","type":"task","status":"open","priority":0,"labels":null,"assignee":"","created":"2026-02-14T16:42:20.13241547Z","updated":"2026-02-14T16:42:20.13241547Z"} {"id":"NK-pumdm4","title":"get rid of the \"selected\" highlight thing","description":"the legacy version doesn't do that and i find it distracting, j/k just move things up/down","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-13T20:27:51.434041661Z","updated":"2026-02-13T22:37:06.185341246Z"} {"id":"NK-qwef98","title":"UI Styling: Controls \u0026 Header","description":"","type":"","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T18:05:18.450759919Z","updated":"2026-02-13T18:11:46.291830432Z"} +{"id":"NK-r6nhj0","title":"import/export","description":"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.","type":"feature","status":"open","priority":1,"labels":null,"assignee":"","created":"2026-02-14T16:45:04.739162003Z","updated":"2026-02-14T16:45:04.739162003Z"} {"id":"NK-ric1zs","title":"Migrate frontend to /api/ endpoints","description":"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.","type":"cleanup","status":"closed","priority":3,"labels":null,"assignee":"","created":"2026-02-13T04:26:55.864725765Z","updated":"2026-02-13T04:26:55.864725765Z"} {"id":"NK-rohuiq","title":"titles changing on read state and hover","description":"Titles are changing on read state from blue to grey. They should just stay blue all the time.\n\nTitles are getting underlined on hover. They should have no underline regardless of hover state.","type":"bug","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-14T03:36:26.36373162Z","updated":"2026-02-14T03:37:50.73870586Z"} {"id":"NK-shpyxh","title":"add search to new ui","description":"","type":"epic","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T19:29:44.251257089Z","updated":"2026-02-14T01:02:58.547025683Z"} |
