Elytra Blog

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

WWDC20 and Elytra

WWDC20 week is currently going and Apple has released all new SKDs for their upcoming OSes for the iPhone, iPad and Macs. There is so much cool new stuff packed into these releases, it was extremely hard for me to evaluate how to proceed with development for Elytra.

During the two weeks leading up to WWDC20, I was working on the Mac Catalyst App for Elytra, trying to figure out if it would be a good fit. Turns out, yes, but with some undesired effects. 

During the same time, I’ve been working on v1.8 of the app for the Fall release to coincide with the releases of the new OSes. 

Unfortunately, all the new amazing APIs Apple is releasing this year for developers to use are tricky to backport to iOS/iPadOS 13 and macOS Catalina. So to make things easier for users of Elytra, you: I’ve decided on the following roadmap:

  1. v1.8 will be released as planned for iOS 13 and macOS Catalina. I’ll simply bring this release forward by two weeks, so everyone who plans to stay on iOS 13 and macOS Catalina for a bit longer can continue to use Elytra with the new features I am implementing in v1.8. This also gives me enough time to submit bug fix builds if they are required. 
  2. v1.9 will be released simultaneously with the new OS releases and will be a one-to-one identical release of v1.8 targeting only the new OSes. This will be the new branch that’ll continue onward to future releases of the app across all 3 platforms. 

However, so much will be changing in the app, the v1.9 tag doesn’t make much sense. So I’ll be bumping things to v2.0 for the iOS/iPadOS 14 and MacOS Big Sur release. So this fall, you can expect v1.8 and v2.0 of Elytra. 

I have some really exciting things planned for these releases. I’ll also be merging the release of Elytra of Web with the 2.0 release of the apps. 

With some careful planning on my part, I hope to have all existing and new users of Elytra up to the latest features with a solid foundation for future releases. 

In the meantime, here’s a look at the new App Icon coming with v1.8 and v2.0 of the apps. 

New App Icon for Elytra

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! 

Elytra Web is now in Public Beta

Elytra Web in Safari with Article open.

Elytra for web is now in public beta and in this post I’ll document some features and quirks of the webapp. You can start using it right away.

When I set out to build the Web App, I wanted to bring as much functionality of the iOS App as possible, and this proved to the tricky. Since version 1 of the app, the Article Reader never used HTML to render the contents. Everything was drawn native to bring native accessiblity functions and remove privacy-sucking scripts from the entire reading experience.

To do the same on the web with the same data was a tad bit challenging, but not impossible.

Elytra Web in Safari with Article open. Some features are notably missing at the moment like:

  • Viewing and reading your bookmarks
  • Searching Feeds
  • Synced settings

to name a few. I’ll be adding these over the next couple of days and I hope to align the final release of the Web App along with v1.8 of the iOS App.

Elytra Web in Safari with Article open. Just like the iOS App, you can also view your Youtube feeds in the Web App. This has become the de-facto way of me and some hard critics of Elytra to consume the latest content from their favourite Youtube Creators.

Elytra Web in Safari with Article open. Microblog Feeds also get first-class treatment on the Web App just like the iOS App. I am a supporter of what Micro.blog stands for and try to actively use it as time permits. My main website is basically a hosted Micro.blog.

Elytra Web in Safari with Article open with a seaprate window open with a podcast playing. I am really exicted to talk about this feature. I’ve always wanted to listen to podcats in Elytra on iOS but I believe it deserves its own separate app so it does not come in the way of reading content. But things are different on the web. Browsers can host multiple tabs for the same domain. So now on the web, you can open any article in it’s own tab and continue reading another article in the main window. I personally use this to play a podcast in the background while I work or read other articles. I’d love to hear from you how you use this feature.

As some of you may have noticed, I have used the New York font in one of the screenshots. If you have the font installed on your macOS systems, you will be able to use in the App as well. The app does not host the font itself because of its License, but can use it if you have it installed.

We now also have a Slack Group for discussions around the iOS and iOS app and soon the macOS App as well. I’d love to see you there and join in on the discussion.

It’s been a tremendous journey for Elytra since its inception back in 2016 and it’s public launch in 2018. As an Indie Developer, I’d really appreciate it if you shared this post with your friends who may be looking for an RSS Feed Reader on the web. As this is a public beta, everybody is welcome. And as always, you can send support queries to support@elytra.app or DM me on Twitter. 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. 

Why Elytra is Fast

Brent Simmons writing on his blog, Why NetNewsWire Is Fast, I realised how similar a lot of stuff is between the two, albeit, Elytra offloads a lot of the feeds syncing to its API. The similarities still do exist. 

NetNewsWire is fast because performance is one of our core values. Being fast is part of the very definition of the app.

The best general advice I can give is just this: make sure performance is part of the foundation of your app. Make sure it‘s part of every decision every day.

Every app, irrespective of the platform, technologies and, toolchains should aim for that. And that’s not technical, it’s behavioural, on our part. 

The most painful way to parse XML is with a SAX parser — but it’s also how you’ll get the best performance and use the least memory.

Yes. It’s a pain in the *** to deal with, but the only proper way to handle thousands of feeds. Elytra’s Polling Server (yes, 1, a t2.nano EC2 instance) chugs through 1K+ Active Feeds 1,not including RSS Feeds which support WebSub, in under 3 minutes.

The parsers are fast — but we also do our best to skip parsing entirely when we can. There are two ways we do that.

We use conditional GET, which gives the server the chance to respond with a 304 Not Modified, and no content, when a feed hasn’t changed since the last time we asked for it. We skip parsing in this case, obviously.

Always respect cache headers for RSS Feeds. Some Feeds when publish a frequency property which you can respect, Elytra does not do that. Elytra uses the Last-Modified and Etag headers specifically. 

Now say you’re marking all articles in the current timeline as read. You could call article.read = true for each article — and, for each article, trigger a whole bunch of work. This can be very, very slow.

Elytra v1.0 did this silly thing, a notification for every change and no coalescing. I fixed that in v1.1 once the number of feeds started growing and I had more and more articles I marked read in bulk. 

So, instead, we coalesce these — we make it so that recalculating unread counts happens not more often than once every 0.25 seconds (for instance). This can make a huge difference.

This is a fantastic idea. I’m going to use this to Elytra in v1.8. 

What I suspect is less common is use of sets. The set is our default collection type — we never want to check to see if an array contains something, and we never want to deal with duplicate objects. These can be performance-killers.

I believe Brent and I ran in to the same issues with fetching Articles from the database such that Sets was the obvious choice over Arrays. I use NSMutableOrderedSet to be specific. 

I finally come to the point I currently disagree with Brent on: 

My experience with stack views tells me that they’re excruciatingly slow. They’re just not allowed.

No Auto Layout in Table Cell Views

Brent has his own reasons here which he describes in his post. I really like Stack Views and it becomes easy for me to think about layouts for the iOS App and the Web app as its very similar to the flex layout model on the web. I have so far not come across performance issues with using Stack Views in Elytra. 

No Auto-Layout in Table View Cells is a deal-breaker for me. Apple’s recent work on self-sizing cells, diffable datasources and composable collection view layouts has really simplified writing code for interfaces. The best part is: with every major OS release, these things become slightly faster, slightly better, and sometimes much faster and better. 

I do miss writing up interfaces in code, but I often found myself fighting the OS when Apple releases new device sizes, requirements (like split-view on the iPad in the past), or new technologies. 


I was happy to read that most of what I am doing in Elytra is very similar to Brent’s approach for NetNewsWire. I first heard about him when Vesper came out and have since followed his work and blog. I have much to learn from him and I hope he never stops writing such posts. 


1. An Active Feed is any RSS Feed which is at-least subscribed by one user. All other feeds are polled once per day.

TestFlight Changes

I’ve been contemplating on this decision for a while now and I think it’s finally time to implement a major breaking change in Elytra’s TestFlight policy. All future releases of Elytra on TestFlight will require you to have an active and valid subscription. 

Since before v1.0, all testers using Elytra through TestFlight bypassed all subscription checks. This is generally what is expected. However, some people are using this to bypass subscriptions entirely. 

This however doesn’t mean all testers will be affected. I know those who actively share feedback, crash reports and communicate with me. I’ll maintain your subscriptions for free for as long as you wish to be on TestFlight program. Everyone else getting started can use the free trail and as required contact me for a a bump in your subscription expiry dates. 

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. 

Updated Pricing

The global pandemic is not coming to a state of resolution any time soon. States across the globe are issuing lockdowns. Since we’re going to be stuck indoors for sometime, I have decided to slash the rates of all Elytra Non-Renewing Subscriptions to half their standard price. This pricing will be applicable up to 30th April, 2020. I’ll retain these prices if the global situation does not improve.

For brevity:

  1. 1 Month: USD 0.99 / INR 79.
  2. 3 Months: USD 2.99 / INR 249.
  3. 12 Months: USD 11.99/ INR 899.

If you have any questions, please feel free to email me at support@elytra.app.

If you’re a student, please email me and I’ll hook you up with some free upgrades.

Stay safe.

Update 1 (2020-04-24 10:40AM IST): The above pricing will be the new standard pricing and will not revert back on the 30th of April.

v1.6.2 Submitted for Review

I just finished submitting the v1.6.2 build for review. It’ll be released automatically to everyone once it passes review and finishes processing for the App Store. 

It fixes two bugs: 

  • Fixed a bug which caused the app to launch with the Empty State Interface with no way to navigate within the app when opened in split-view mode on compatible iPads.
  • Fixed a crash that would occur when launching the app from a cold state.

I’m also happy to note that work on v1.7 of the iOS app is nearing completion. It won’t be released until Summer, 2020 though. It’ll be released alongside something else. So stay subscribed to know more about that.