Manage your RSS Feeds from the extension popup.
- Manage RSS feeds locally. No account required. Your data stays on your device.
- Back up and restore all the extension data (feeds, folders, posts, bookmarks and settings). Details of the backup format can be found below.
- Export and import feeds as OPML.
- Organize feeds into folders with drag and drop support.
- Search for posts already fetched by the extension.
- Support for RSS, Atom and JSON feeds.
- Support for keyboard navigation. The list of shortcuts is below.
- Light and dark themes.
- Pick up where you left off if the popup closes accidentally.
- Mark posts as read by clicking them (with a setting to allow clicks to open the post instead).
- Middle and right-click to open a post.
- The back/forward mouse buttons work just like in the browser tabs. Or, use the keyboard shortcuts instead
ctrl+alt+left/ctrl+alt+right. ctrl+fto filter recent posts andctrl+shift+fto search all posts.- Hover over a link to view the URL at the bottom of the extension popup (Chrome does not do this for links in the extension popup).
- An icon with a link to the comments URL is added to the bottom of the post when a comments link is available. This is pretty handy for feeds like 'Hacker News'.
- Posts are grouped by feed when viewing all posts under a folder (with a setting to disable posts grouping).
- Automatically check for feeds in the current tab when adding a feed.
- Turn off auto-updates for specific feeds.
- Bookmark posts.
- No Sync with other devices. Make sure to create extension backups regularly from the "Preferences" tab.
- Cannot view the full post in the extension. I think it's best to view posts on the author's website and the extension popup isn't the place for reading articles anyway.
- No notifications. I don't like notifications.
I used Feeder's Chrome extension for years. I was mostly happy with it, especially that it didn't require a login. But, there were some small issues that kept nagging at me and minor improvements that I wanted to add. So, I thought: why not create my own extension. And, this is the extension I'm using instead.
The backup is a zip file containing the following JSON files:
-
manifest.jsoncontains the backup metadata:backupVersionset to1. Will be incremented only when there is a breaking change.extensionNameextensionVersionthe extension version when the backup was generated.createdAtwhen was the backup generated.preferencesthe user preferencesuiTheme"light"or"dark"ornull(i.e. follow system theme).defaultFeedUpdateFrequencythe default value in milliseconds for the 'Update Frequency' field when creating a new feed.clickPostToToggleUnreadwhen set totrue, clicking a post marks it as unread. When set tofalse, clicking a post opens the post in a new tab.orderPostsByposts in a feed, under a folder, under bookmarks or in search, can be ordered bypublishedAtorfetchedAt.publishedAtis the time when the post was published according to the feed.fetchedAtis when the post was fetched by the extension from the feed.groupFolderPostscan betrueorfalse. Iftrueand when displaying posts inside a folder, posts for feed X will be shown first, then posts for feed Y, ... This grouping will be done for each page of posts.
backupFilesfeeds_foldersthe filename containing the feeds and folders data. Usually set tonodes.json.postsan array of filenames (0 or more) containing the feed posts. Each file contains at most 20K posts. Usually namedposts_xxxx.json.
-
nodes.jsoncontains an array of feeds and folders. Each object has the following propertiesidauto-incremented integer.typecan be"feed"or"folder".namename of the feed or folder.unreadCountthe number of unread posts inside the feed or folder.parentIdID of the parent folder containing this feed or folder. Can benullonly for the root folder.sortOrdera number that allows sorting feeds and folders within the same parent foldercreatedAtwhen was the feed or folder created.feedset tonullfor folders. Contains the following properties whentype="feed"urlfeed URLfaviconURL of the feed icon. can benull.updateFrequencyfrequency of feed updates in milliseconds. Can benullmeaning that the feed will not be updated automatically (user can still do that manually).lastRunAtlast time the feed has run. Represented as an integer (milliseconds since epoch). Can benull.nextRunAtnext time the feed will run. Equal tolastRunAt + updateFrequency. Represented as an integer (milliseconds since epoch). Equals tonullwhenupdateFrequencyisnull.
-
posts_xxxx.jsoncontains an array of feed posts. Each post has the following propertiesfeedIdfeed IDguidstring representing the unique identifier for the post. Provided by the feed.titletitle of the posturlURL of the postcommentsURLURL pointing to the comments of the post. Only RSS feeds can provide a comments URL (Atom and JSON feeds do not).unreadcan be1(unread) or0(read)bookmarkedcan be1(bookmarked) or0(not bookmarked)publishedAttime the post was published according to the feed. Represented as an integer (milliseconds since epoch).fetchedAttime the post was fetched by the extension. Represented as an integer (milliseconds since epoch).
Tabbing through the UI elements and using arrows allow you to do almost everything. Still, some of the following shortcuts might prove useful:
ctrl+shift+sto open/close the extension popup (can be configured fromchrome://extensions/shortcuts)- Top-header shortcuts
ctrl+lgo to the "Library" pagectrl+bgo to the "Bookmarks" pagectrl+pgo to the "Preferences" page
- Filter/Search posts
ctrl+fgo to the filter posts page. Enabled in feed/folder/bookmarks/search pagesctrl+shift+fgo to the search posts page. Enabled in feed/folder/bookmarks/filter pagesescapeexit from filter/search page and go back to the previous page
- Back/forward navigation (the same as the browser back/forward buttons)
ctrl+alt+leftgo backctrl+alt+rightgo forward
- Page Header Navigation (under "Library")
ctrl+ttoggle the feed/folder title dropdownctrl+mmark all posts in the current feed/folder as readctrl+ugo to the unread posts page of the current feed/folderctrl+ago to all posts page of the current feed/folderbackspacego to the previous page (same as clicking the back button that is rendered in the extension UI)
- Navigating the folders/feeds hierarchy
up/downmove up/down in the folder/feed listright/enterwhen a folder/feed is focused, go to that folder/feed pageleftgo to the parent folder pagettoggle the three-dot menu of the focused feed/foldermmark as read all posts of the focused feed/folder.ugo to the unread posts page of the focused feed/folderago to the all posts page of the focused feed/folder
- Posts page
up/downmove up/down in the posts listleftgo to the parent folder pagelload more postsenteropens the link in a new tab or toggles the unread status of the post depending on the user preferencesctrl+enteropens the link in a new tabshift+enteropens the link in a new windowctrl+shift+enteropen the focused post in a new incognito window and move to that windowctrl+ccopy the link of the focused postkopen the comments link (if any) of the focused post in a new tab and move to that tabctrl+kopen the comments link (if any) of the focused post in a new tab but keep the focus on the extension popupshift+kopen the comments link (if any) of the focused post in a new window and move to that windowctrl+shift+kopen the comments link (if any) of the focused post in a new incognito window and move to that windowbbookmark or remove the bookmark of the focused postmmark the focused post as read or unread
- Install dependencies:
npm install- Start development server:
npm run dev- Open Chrome and navigate to
chrome://extensions/, enable "Developer mode" and load the unpacked extension from thedistdirectory.
src/popup/index.html- Extension popup UI.src/background/index.ts- Extension service worker. Includes message handlers for managing extension data (stored in indexedDB), feed polling for new posts, caching,src/offscreen/index.html- Handles feeds export, backup/restore and search.manifest.config.js- Chrome extension manifest configuration.
- [optional] Set env variable
GITHUB_TOKEN(generate token) - Run
npm run releasewhich includes:- Pull the latest changes
git pull. - Check for linting issues
npm run lint. - Set the new version in
package.json - Add the version and date to the changelog
## [<version>] - <yyyy-mm-dd>and keep## [Unreleased]at the top. - Commit the changes and create a git tag
v<version>. - Push the local commit and tag to GitHub.
- Create the GitHub release, done automatically if the
GITHUB_TOKENenv variable is set. Otherwise, a new release page is opened in the browser with fields prepopulated. The release notes are copied from the changelog.
- Pull the latest changes
- Package the extension with
npm run build. - Upload the packaged extension to the Chrome web store.
This project is GPLv3 licensed.
