Summary
I built a full RSS/Atom feed reader for Odysseus on my fork and would like to know if there's interest in contributing it upstream. It's not a small patch — it's a new feature area (~2,400 lines across backend + frontend), so per CONTRIBUTING.md I'm opening this issue first to describe the approach before any PR.
Full disclosure: this was built with AI assistance (Claude Code), with me steering scope, reviewing changes, and testing everything live against a real feed subscription list. I'm not trying to land this as a bulk auto-generated PR — I want to check in first per your stated process, and if there's interest, work out with you how to split it into reviewable chunks.
What it does
A 3-pane feed reader (sidebar / article list / reader view) that lives alongside the existing panels (Notes, Email, etc.):
- Feeds & groups: add feeds via URL discovery, nested groups (nest groups inside groups), drag-and-drop to reorder feeds or move them between groups, OPML import/export (preserves group hierarchy), batch select/move/delete.
- YouTube support: paste a channel URL/handle and it resolves to the channel's video feed automatically; favicon resolution.
- AI summaries: per-article and per-group (digest) summarization using whatever LLM endpoint is already configured in Settings. Falls back to fetching the actual video transcript for YouTube entries, since
feedparser leaves content empty for a lot of them.
- Reading UX: keyboard shortcuts (j/k navigate, m mark-read, s star), Prev/Next toolbar buttons, infinite scroll, full-content fetch (trafilatura) for feeds that only publish snippets, TTS playback of articles, star/read tracking, search/filter (unread/all/starred).
- Scheduling: optional per-feed refresh interval + an opt-in background task (off by default) that auto-refreshes feeds on their configured interval, wired into the existing task scheduler.
Approach / architecture
- DB:
FeedGroup (self-referential parent_id for nesting), Feed (group_id, fetch_interval, sort_order), Article — all in core/database.py, migrations follow the existing manual ALTER TABLE pattern already used in that file (no Alembic in this repo).
- Backend:
services/feed/ (fetcher via feedparser, discovery, OPML parse/build, full-content via trafilatura, YouTube channel resolution + transcript fetch) and routes/feed_routes.py (CRUD, refresh, summarize, OPML import/export).
- Frontend: a single
static/js/feedReader.js module + scoped CSS, following the same panel pattern as Notes/Email (centered modal, drag/dock/fullscreen via the existing makeWindowDraggable helper). Reuses existing shared modules where possible — the drag-and-drop reordering uses the already-shared dragSort.js (same one Models/Sessions/Gallery use) rather than introducing a new drag library.
Test steps I ran
Full backend suite passes (4600+ tests). For the feature itself: added/removed feeds and groups, imported a real OPML export, dragged feeds between groups and collapsed/expanded groups, ran AI summarization against both a local Ollama model and a slower hosted model to confirm it handles varying response times, verified YouTube channel resolution and transcript fallback against real channels, tested keyboard nav and infinite scroll against a feed with 1000+ articles.
Open questions for you
- Is there interest in RSS as a feature area for Odysseus at all, or is it out of scope for the project's direction?
- If yes — would you rather review this as one PR, or should I split it into a stack (e.g. core CRUD + UI, then AI summary, then drag/keyboard/scroll polish, then scheduling)?
- Any existing conventions I should double check against before submitting (e.g. is there a preferred pattern for new "panel" features I should follow more closely)?
Happy to share screenshots/a short clip of it running if that's useful before you decide.
Summary
I built a full RSS/Atom feed reader for Odysseus on my fork and would like to know if there's interest in contributing it upstream. It's not a small patch — it's a new feature area (~2,400 lines across backend + frontend), so per CONTRIBUTING.md I'm opening this issue first to describe the approach before any PR.
Full disclosure: this was built with AI assistance (Claude Code), with me steering scope, reviewing changes, and testing everything live against a real feed subscription list. I'm not trying to land this as a bulk auto-generated PR — I want to check in first per your stated process, and if there's interest, work out with you how to split it into reviewable chunks.
What it does
A 3-pane feed reader (sidebar / article list / reader view) that lives alongside the existing panels (Notes, Email, etc.):
feedparserleavescontentempty for a lot of them.Approach / architecture
FeedGroup(self-referentialparent_idfor nesting),Feed(group_id,fetch_interval,sort_order),Article— all incore/database.py, migrations follow the existing manualALTER TABLEpattern already used in that file (no Alembic in this repo).services/feed/(fetcher viafeedparser, discovery, OPML parse/build, full-content via trafilatura, YouTube channel resolution + transcript fetch) androutes/feed_routes.py(CRUD, refresh, summarize, OPML import/export).static/js/feedReader.jsmodule + scoped CSS, following the same panel pattern as Notes/Email (centered modal, drag/dock/fullscreen via the existingmakeWindowDraggablehelper). Reuses existing shared modules where possible — the drag-and-drop reordering uses the already-shareddragSort.js(same one Models/Sessions/Gallery use) rather than introducing a new drag library.Test steps I ran
Full backend suite passes (4600+ tests). For the feature itself: added/removed feeds and groups, imported a real OPML export, dragged feeds between groups and collapsed/expanded groups, ran AI summarization against both a local Ollama model and a slower hosted model to confirm it handles varying response times, verified YouTube channel resolution and transcript fallback against real channels, tested keyboard nav and infinite scroll against a feed with 1000+ articles.
Open questions for you
Happy to share screenshots/a short clip of it running if that's useful before you decide.