Elytra Blog

The simple RSS Reader. This blog publishes release notes, engineering and design details.

Introducing Neptune

Prelude

RSS Feeds are amazing! Many of us have built entire apps, services and businesses around it. The specifications for it have existed for a long time. Newer specifications like JSONFeed are powering new workflows around it.

Earlier in the previous decade, websites began injecting ads, trackers into their RSS feeds. Those were easy to get around for Elytra.

However, soon after the rise of Ad Blockers and similar technologies, more and more websites wanted people to open their web pages through their RSS feeds. This leads to websites providing only truncated excerpts in their feeds.


This become a legitimate problem soon after Social Media Giants began fiddling with users feeds by converting a timeline to a suggestions list like the coupons section from a local newspaper ¯\_(ツ)_/¯.

To solve this problem, a lot of genius services like Postlight’s Mercury popped up. They provided a huge boost to feed reader apps (and many others). Almost every app I used before Elytra used it. Elytra used it up till version 2022.2.4.

However, Postlight later made Mercury an open-source project which didn’t receive much attention from the original authors and the community since 2019. I tried to add my own patches to it however, it became tedious to maintain in its current form without doing a complete rewrite against the latest tooling and NodeJS versions.

Since I was considering a rewrite anyway, I thought to myself: why not do it with my new favourite programming language as of 2022: Swift. And as I was going to rewrite things, why not do it simpler (if not better!).

Introduction

This led me to create Neptune, a pure Swift based system to fetch and parse full-text content from webpages for Elytra. It’s fast, very very fast (more details below) and uses a simpler logic compared to mercury to parse and process webpages.

The Swift programming language, by its design, leads to type safe code that brings fewer surprises compared to NodeJS. It also compiles down into a single executable binary, which has its own tradeoffs, but brings three powerful, key features:

  • maintainability
  • performance
  • more performance

Numbers

Oh, and I’m not kidding. On a tiny t3.nano (512MB RAM, 2GB swap, 1vCPU) server, these are some numbers:

Process 0.1K Articles 1K Articles 10K Articles
Mercury 28s 378s 3500s
Neptune 12s 135s 1428s
Change +40% +41.17% +42.05%
  • These tests were performed with the t3.nano instance having full CPU credits available to it.
  • These tests did not persist any data to disk by itself.
  • These tests were performed in partial isolation: only the process being tested was run along with the test script.

If you’re asking yourself, what the numbers mean for you: the answer is quite simple: Neptune is very quick at fetching full-text context from your favourite blogs. Additionally, because it’s simpler to maintain and upgrade, adding support for new websites is vastly simpler and requires only a few lines of code of me (sometimes only 6 lines, 4 of which are bootstrap code).

The Future

I’m sure Neptune is not ready for any commercial use, not in its current form anyways. But I will eventually offer Neptune as a standalone service for other apps to use. I’ll document this at a later point in time.

Users of Elytra can take advantage of Neptune starting with the v2022.03 release as the default extractor. No settings to toggle. It’s all set up.

If you spot any issues, or articles from specific websites failing to load, please submit an issue on Github. It has a standard format making it easy for you to submit reports. I look forward to reading from you about your experience with Neptune.

February 2022 Update

Elytra got multiple releases in February. This post outlines the changes across all those releases and acts as a monthly summary of things happening here.

Version Numbers

Starting with the recent releases, the versioning scheme for the apps has changed. The previous version numbers wouldn’t make much sense to either of us, except for identifying a particular release.

That’s not helpful if I have tens of builds for the same version and the macOS and iOS apps are running two separate builds for the same version.

Now, the versions are numbered as year.month.release, the latest release being 2022.02.4. That makes it easy for the both of us to identify when this build was released. For people browsing the App Store, it’s a clear indication of a regularly updated app as well.

Changes, Improvements and Fixes

Improvements

  • Added new keyboard shortcut to load Full-Text when an article is open.

  • Updated Japanese translations

  • Improvements to bulk marking read and improvements around on-device logging for the same.

  • Hint for externally opening articles

Fixes

  • Some fixes around images from specific hosts failing to load.

  • Fixed some issues around fetching full-text.

  • Fixed a bug causing full-text cover images not being drawn in the article view.

  • Fixed an issue with some attachments not appearing in articles.

  • [iOS] Added Logs viewer and export under settings.

  • Fixed swipe action on article not correctly marking an article as unread.

  • Clear local data correctly when resyncing.

  • Fixed shadows of the categories in the New Feed section.

  • Fixed a crash when processing block quotes in some articles.

  • Fixed a crash occurring after a successful OPML import.

  • Fixed crashes around importing feeds from OPML files.

  • Fixed feeds not mapping to folders when importing structured OPML files.

  • Fixed a bug with first time account setup causing multiple not-found errors in some cases.

  • Fixed a crash when syncing new articles which only contain a cover image.

  • Fixed adding a new feed directly to a folder.

  • Fixed feeds resync discarding feed settings.

  • Fixed feeds resync not remembering custom feed names.

  • Fixed shadows of the categories in the New Feed section.

I’m going to make this a habit: post a monthly summary at the beginning of each month so changes to app can be clearly tracked and if we missed out anything, we can go back and look at these logs to figure things out.

There are a few new repos I’d like to mention here:

  • Localisations All the translation files used by Elytra. If you find a mistake in a translation, please feel free to submit a correction there. You can also add a new language that you’re comfortable translating to. The contents of that repo use a permissive license, so other developers can also use translations that fit their apps from there.

  • IssueTracker The Issue Tracker is a public repo for tracking bugs and feature requests. If you have one, please open an issue there with the correct type so other users with similar requests can also chime in.

Thank you for reading, have a safe and cheerful day.

Elytra v2.4 is now available

Elytra’s 2021 third quarter release is here and is ready for iOS and iPadOS 15.

This is the first release with a modern and cutting-edge foundation which focuses on reliability, stability and ease of adding new features in future releases.

If you feel generous and have a couple of minutes, please review the app on the App Store. It makes a huge difference for me. Thank you in advance.

New

Quick Notes

Quick notes has been one of my favourite additions to iPadOS 15. You can quickly reference articles using it in your notes with a simple drag and drop.

Prominent Scene

The inclusion of prominent scene is a great addition to the multitasking arsenal on iPadOS. Simply pinch out from an article to open it inside its own prominent scene.

Extra Large Widgets

Elytra's extra large widgets for iPadOS 15

Extra large widgets on the iPadOS 15 makes getting a quick overview of recently fetched articles even easier. All widgets have been updated to support this new size.

Other New Additions

  • Added a new sync method to also sync added and deleted feeds on sync.
  • Added a new Portrait Lock preference under miscellaneous settings.
  • Added support for tables in articles.
  • New and improved article list view. It renders twice as fast now and uses less power overall.
  • Added a “Enable Push Notifications” toggle under Settings > Notifications. You will only see it if Push Notifications are not already enabled on that device. For cross-device sync, it is recommended you turn this on.
  • Added the old v1 app icon to the list of customisable icons.
  • New options for Feed Settings:
    • Open Articles in the Browser. This is useful for feeds where full-text extraction fails.
    • You can now toggle full-text fetching for feeds. When you open an article from that feed, the full-text content will be automatically loaded.

Improvements

  • Categorised keyboard shortcuts on iPadOS.
  • Added a small bar underneath the status bar when you have the hides bars preference enabled. This prevents underflow of the content and helps prevent the distracting “text over text” situation.
  • New Photos Browser
  • Improved external display/Airplay handling
  • If you add multiple folder widgets, you can configure each one with a unique folder. The previous limitation of a single folder has been fixed. (back-ported to iOS 14).
  • Improved error messages across the app. The app will now display error messages directly from the API’s error.
  • Added delete and info swipe actions to the search results for Feeds.
  • Notifications under the app settings will now also show Local Notifications if any are enabled.
  • Improved scrolling performance on iOS 14 and 15 inside the article reader.
  • New and improved settings UI.
  • New Appearance customisation UI in the article reader (on iOS 15, it’ll appear as a bottom sheet).
  • Improved visuals for the folder row if a feed is being dropped onto it.
  • Improved dragging states for feeds and articles.
  • The sidebar now maintains the folders expansion state across app launches.
  • Added the cmd + G (cmd + shift + G for backwards) shortcut for navigating to the next article search result.
  • Added Keyboard shortcuts to dismiss interfaces like New Feed, Feed Info and other modals.
  • Improved sync and timeline loading performance for users with several filters.
  • Added the ability to reuse your existing account ID for signing in to the app. Please contact support on details on how to use this.

Fixes

  • Fixed an issue where marking some articles as read failed if they were recently synced on to the device.
  • Fixed an issue across all platforms that could sometimes cause a crash on launch when available system memory is low.
  • Fixed an issue with the title view in the articles list being hidden after scrolling.
  • Fixed an issue when swiping back from the article reader when the bars are hidden to cause the layout to get janked.
  • Fixed an issue with the new sync not updating the feed’s folder structure if one already exists.
  • Fixed a crash that was caused when changing from light to dark mode and the article reader was open.
  • Fixed an issue with the Article Reader’s bottom helper view used a black background and black shadow causing it to appear blurry for some users.
  • Potentially fixed a crash for some users when using the toolbar preference.
  • Fixed a crash that would sometimes occur when opening an article with Lists containing multiple line-breaks at the beginning of the paragraph.
  • Fixed a long standing issue on iPadOS where the currently selected article or sidebar item would get deselected when the app was backgrounded and then foregrounded again.
  • Fixed a bug with importing OPML Files with invalid/incorrect format.
  • Fixed an issue where the feed settings would not be loaded correctly on app launch.
  • Fixes an issue which caused Feeds only re-sync to fail which also caused background sync to fail sometimes. This could potentially cause feeds metadata to get wiped.

Elytra Winter 2020 Update

The Winter 2020 update is finally ready in 2021! This is the first release of Elytra which brings local sync, local notifications and a lot of performance and stability improvements to the apps.

Similar to Elytra v2 and v2.1, this is an iOS 14 only release. The latest supported version for iOS 13 is v1.8 and will be deprecated soon.

You can download the update from the App Store. If you feel generous and have a couple of minutes, please leave a review on the App Store. It makes a huge difference for me. Thank you in advance.

Local Sync

Elytra v2.2 running on Macbook Air, iPhone XS and iPad Air This release brings Local Sync to the apps. Local Sync caches all articles across all your feeds (just like other RSS Feed Reader Apps). This is not a “new” technique. Feed Reader apps have been doing this for as long as I can remember. Elytra now uses the same technique by leveraging its APIs to make the entire process a lot faster!

Elytra does not have to check every single feed if it has new updates. It uses a single API to check if updates are present, and if they are, sync them to your devices.

Full Change Log

New

  • Local Sync. All feeds are now synced to your device locally, so you can continue reading even when your device is offline.
  • Added a new “Title View” to individual feeds. Open a feed and tap on its title. This shows the Feed Info and two preferences at the moment: Push/Local Notifications & Safari Reader Mode. These are per feed settings. This is very similar to the design and functionality from NetNewsWire, is directly inspired by it, but with a minor difference: the layout and copy denotes which feeds support Push Notifications, while the others supporting Local Notifications.
  • Push Notifications Request Form. If you already have push notifications enabled, you won’t see this. This is per device.
  • Added support for background push notifications to keep all your devices in sync without needing manual refreshing.
  • Push Notifications for new articles now download and cache the article for immediate use.

Improvements

  • Tapping on a folder now opens the folder’s feed.
  • Tapping on the disclosure icon on a folder now toggles its expanded state.
  • Filtering is now stricter. It’ll match “sponsor” but will not match “sponsored”.
  • Added Feeds to the iOS Search Index. You can now directly open feeds by their names (or custom names if you have one set).

Fixes

  • Fixed the tint colour for the blog name when opening a micro-blog article.
  • Fixed adding feed by URL where the feed presents multiple options.
  • Fixed an issue when searching by title for 3-letter sites like CNN or BBC.
  • Fixed articles not loading for certain feeds.
  • Fixed Today View not updating when opened after an app launch.
  • Fixed an issue with the iPadOS app showing different widths for the columns in different orientations or environments (split view).
  • Fixed an issue with the apps not correctly download bookmarks from the API.
  • Fixed an issue where toggling folders in the sidebar interface would show empty folders.
  • Fixed an issue with certain CJK paragraph blocks rendering incorrectly when certain linebreak characters are used in the paragraph text.
  • Fixed an issue with filters incorrectly hiding articles when matching against CJK based filters.
  • Fixed an issue with line-heights in the articles list for multi-lined article titles with favicons.
  • Fixed an issue where the “no articles” label would appear over the articles.
  • Fixed an issue for adding Streaming Video Channel feeds. They recently changed their format which was causing issues.
  • Fixed a crash when writing the widgets data to disk when the app has just been sent to the background.
  • Fixed Navigation Bar buttons not appearing in some contexts.

Thank you for reading.

Elytra Fall 2020 Update

Elytra’s Fall 2020 update is finally here alongside the release of iOS 14. This is v2.0 and will be the first build to only support iOS 14. If you’re still on iOS 13 and for whatever reason you won’t be updating to iOS 14 soon, rest assured, v1.8 will continue to function as long as you use it.

You can download the update from the App Store

Upcoming Devices

Elytra running on 4th Generation iPad Air

Apple will be releasing new hardware later in October starting with the recently announced new iPad Air 4th Generation devices. Elytra will be ready on day-1 when these devices reach you with no new updates required.

iOS 14 UI

Elytra running on the iPad Pro and on the iPhone 11 Pro showing new User Interface elements from iOS 14

Throughout the app, I’ve made changes to the app’s interface to closely follow new updates Apple has released this year, including menus from buttons (for the sorting option), new Sidebar Layout style on the iPad, Triple Column Layout on the iPad and new List styles.

New Code Theme

The new code theme in Elytra 2.0

Also in this release, I’ve included a new Code theme which uses the semantic colours from iOS, auto-updates for dark mode without reloading the entire stack and, may I say so myself, looks beautiful. You can read more about in this blog post I wrote earlier.

Widgets

How could an iOS 14 release build be complete without new Widgets! I’ve personally been looking forward to using Widgets and making them was fun too! Elytra 2.0 ships with 2 different widgets:

  • Counters Widget: Shows the latest counts of articles from Unread, Today and Bookmarks sections of the app. This widget is only available in the small size.

  • Unread: Shows the latest articles from the unread section. The medium size widget shows 2 articles and the large size widget will show 4 articles. This widget will prioritize articles with cover images.

Full Change Log

What’s New

  • All new triple column support using Apple’s own UI Framework.

  • An all new Sidebar Interface. This uses Apple’s latest UI Framework for displaying your folders and feeds.

  • iOS 14 Widgets support. Contains a Counters (Small) Widget and an Unread Articles (medium and large) widget.

  • Implements Trailing Swipe actions on Article List Items.

  • Directional marking as read. Long press on an article in Unread, Today or a Feed to see these options.

  • New Code Theme for pre-formatted code blocks.

  • The Add Feed interface now shows Recommendations for its default state to help improve finding and adding new feeds.

Improvements

  • Unread counts update more reliably as you read through your content.

  • Improved underlying code for managing the initial state of the app.

  • Force touch and tapping on urls now works reliably.

  • Updated Feed Sorting options to use a menu interface instead of an options controller.

  • Improved styling for inline code blocks.

  • New Folder/Edit Folder interface now uses a basic interface which is faster to use IMO.

Fixes

  • Prevents an issue causing the app to sync data twice upon successfully launching.

  • Fixes an issue where marking currently loaded articles as read in the Unread view would prevent new articles from loading.

  • If you have setup a custom title for a Feed, the custom title will now show up correctly for the empty state.

  • Fixed a crash caused when trying to share a Feed’s URL or its website’s URL.

  • Fixed an issue where reading an article from today would not decrement the “Unread Today” counter.

  • Fixes showing cover images inside the Article Reader.

  • Fixed I/O View not appearing when importing / exporting OPML files.

  • Fixed some pre-formatted quotes appearing as single-line code blocks.

  • Fixed code blocks appearing out of order. A year old bug finally fixed!

This update also includes miscellaneous improvements and fixes under the hood to improve the general stability of the app.

As recently put by one of Elytra’s admirers on twitter:

Read more, distract less. #letsgo

Hardik Parmar

June 2020 Web Service Update

I’m starting a new series of posts detailing changes I release to the Web Service. The Web Service is responsible for syncing your account across your devices and browsers. It also caches new articles so you only fetch information from sources that have changed since the last sync. 

  • I keep getting error reports from the Web Service in a unified private channel on Elytra’s Slack group. I use these reports to patch bugs as soon and as quickly as I can. 
  • Yesterday, I received some errors regarding adding feeds using the ftr.freshangle.net service. This is the first I had heard about so I quickly investigated and found some issues in Elytra’s code that prevented these feeds from being processed. The ftr.freshangle.net service now has first class support in Elytra for both the XML and JSON feed endpoints. 
  • There was a major sync bug in Elytra’s code both on the Web Service and iOS App. I released v1.7.4 on iOS to patch this issue and patched the Web Service as well. By morning of 4th June, these errors dropped down to just 12% compared to the day before it. As soon as all users update to the latest version of the iOS App, this should drop down to 0%. If you still haven’t updated, check the App Store for updates. 
  • On 2nd June, we faced an interruptions and eventually an outage from our service provider which caused Elytra’s first ever downtime this year. Things eventually began recovering by 03:30AM IST on the 3rd of June. Everything is now stable. This outage resulted in some angry customers and I completely understand that. If you ever face any issues with the App or Service, always feel free to contact me at support@elytra.app

On a separate note, a White Hat Hacker recently got in touch with me regarding a critical issue with the API Service. I have since patched the issue. No data was affected as the core issue had to do with DNS setup for emails sent from Elytra’s domain. 

That’s it for this update. Happy Reading! 

A lot of Unread Articles

If you launch the app or open the web app (if you have access) and notice a sudden surge of unread articles waiting for you, I can explain.

Traditionally, to check if an article is unique and new, I checked its GUID which the feed provides and checked if it already exists in Elytra’s database. This works fine if there is only one source for an RSS feed. It breaks when there are multiple sources for a single website. This happens when say I subscribe to a Website’s XML Feed and someone else subscribes to its JSON Feed. Both sources are valid, but both bring in articles with the same content and GUID. So the articles would map only to the first feed. The second feed would never get new articles. 

To solve this problem, I just updated my unique constraint to also use the Feed’s unique ID. The new unique pair constraint of GUID-FeedID works for all feeds from a single website, irrespective of which source the user subscribes too. 

This caused a huge surge in unread articles for all users. I do apologise for having overlooked this issue, but on the bright side: We all have a bunch of articles to read over the weekend which we missed out on, no thanks to me. 

Summer 2020 Update

The Summer 2020 update is here. If you feel generous and have a couple of minutes, please leave a review on the App Store. It makes a huge difference for me. Thank you in advance. Here’s the full change log:

New

  • Support for Mouse/Pointer Interactions on iPadOS 13.4.
  • New Custom Feed: Today. All articles from the day, read and unread. Sort by your own preference.
  • Now add Youtube Channel RSS Feeds directly from the Share Extension.
  • Article Reader Customisation: You can now customise your reading experience based on your personal preferences. Set line heights, font sizes and individual fonts for paragraphs and headings.

Improvements

  • Improvements for handling Youtube URLs inside the app when adding a new channel feed.
  • Push Notifications will now show richer previews if you open them in context.
  • Show refresh control animation when the app loads and is loading Feeds data from the API.
  • GIFs will now show the first frame if the Image Proxy is enabled.

Fixes

  • Fixed incorrect paragraph line-spacing calculation with the selected value for font size.
  • Fixed an issue where opening a push notification on iPads would open them in the primary column.
  • When you tap on a push notification while another article is open from a Feed, the Feed now correctly deselects the active article.
  • When you tap on a push notification, the app sets up correctly on the iPad. If you tap on a Feed after this, it no longer dismisses the previously opened Article.
  • Fixed a crash when creating a new Folder for the first time.
  • Fixed GIF playback.
  • Fixed an issue where an article would remain marked as Read even after opening it.
  • Fixed font sizes for the Feed description on iPads.
  • Fixed a type bug on the iPad where the font sizes were comically large for titles.

RPC First Class Support

Back in December 2018, I wrote a post about RPC Pings support in Elytra. I cannot believe it has been that long. Later in 2019, I promised to bring first class support to blogs that implement RPC pings to Elytra. 

I have just finished implementation and it is now live. To recap the steps from the earlier blog post, let’s assume you have a WordPress Blog. 

…if your blog runs on WordPress, you can add the following URL: https://api.elytra.app/rpc-ping under > WordPress Blog’s Settings > Writing > Update Services. 

That’s it. WordPress handles all the complexities for you. If you use Micro.blog, you can find instructions here. You can adapt that shortcut to send RPC pings for any website you host as well as to any other service other than Elytra. 

Here’s what happens in the background:

  1. Your website/script sends an RPC ping to Elytra.
  2. Elytra immediately processes your website’s RSS Feed. 
  3. Any new posts are added for your subscribers to read. 
  4. Additionally, users subscribed to your blog’s push notifications from the iOS and iPadOS Apps are sent a push notification.

Starting today, 29 Mar, 2020: Once your blog sends at least 5 pings every 14 days, Elytra will no longer poll for changes to your RSS feed. Elytra will then assume that you will send RPC pings every time content on your website is updated. If no RPC pings are posted for 14 days, Elytra will once again begin polling changes at regular intervals until the 5 pings are received and the cycle can repeat. 

So you get the benefit of real-time updates, push notifications and no penalties for downtime. This hugely benefits users using a blogging platform like Github Pages, Micro.blog, etc. that don’t inherently support WebSub yet. You can use this for your WordPress based blog as well if you don’t want to install the WebSub plugin for whatever reason. 

Starting with v1.7, users of the iOS and iPadOS apps will also be able to subscribe to feeds for Push Notifications which use RPC pings. 

I invite your feedback on this feature if you decide to implement and make use for it. For any questions, please feel free to email me at support@elytra.app. Enjoy Reading. 

Spring 2020 Supplementary Update

Youtube is very wide, densely spread content aggregation service which almost every single one of us has used at least once. Youtube has supported RSS Feeds for channels for a while now; for as long as I can remember actually. Although, it makes it very hard to find and subscribe to them. There is no direct option to do so. 

Until recently, I traversed a channel’s homepage and realised that Youtube advertises these links, like any good citizen of the WWW should. So now when you enter your favourite channel’s URL in Elytra, the app will automatically fetch the RSS Feed URL for you and add it to your account. 

I’ve further programmed Elytra to know the 3 varieties of the URLs Youtube uses for channels and handle all of them gracefully. I’ve personally configured mine to all go inside a Youtube folder so I can tap on the folder to view its custom feed and go through all published videos. 

In v1.6, I also updated how Youtube videos are handled in the app. It now uses the HLS stream which automatically configures the player based on your device settings like Low Power Mode, Low Data Mode, and the like. So it’s very energy efficient compared to opening the main stream or embedding in a web view. 

Unfortunately, Youtube does not support WebPush/PubSubHubBub on these feeds yet, and I doubt they ever will. 

If you need to import all your channels, you can follow Google’s support documentation which can be found here

As always, if you like the app, please take a moment and rate it on the App Store. It helps the app and me a lot. Happy Reading.