inessential by Brent Simmons

Why NetNewsWire Is Not a Web App

Tim Bray writes, on Mastodon, I think correctly:

The canceling of ICEBlock is more evidence, were any needed, that the Web is the platform of the future, the only platform without a controlling vendor. Anything controversial should be available through a pure browser interface.

This is not the first time I’ve had reason to think about this — I think about issues of tech freedom every day, and I still bristle, after all these years (now more than ever), at having to publish NetNewsWire for iOS through the App Store. (The Mac version has no such requirement — it’s available via the website, and I have no plans to ever offer it via the Mac App Store.)

But what if I wanted to do a web app, in addition to or instead of a native app?

I can picture a future, as I bet you can, where RSS readers aren’t allowed on any app store, and we’re essentially required to use billionaire-owned social media and platform-owned news apps.

But there are issues with making NetNewsWire a web app.

Money

I explain in this post that NetNewsWire has almost no expenses at all. The biggest expense is my Apple developer membership, and I pay just a little bit to host some websites. It adds up to a couple hundred bucks a year.

If it were a web app instead, I could drop the developer membership, but I’d have to pay way more money for web and database hosting. Probably need a CDN too, and who knows what else. (I don’t have recent web app experience, so I don’t even know what my requirements would be, but I’m sure they’d cost substantially more than a couple hundred bucks a year.)

I could charge for NetNewsWire, but that would go against my political goal of making sure there’s a good and free RSS reader available to everyone.

I could take donations instead, but that’s never going to add up to enough to cover the costs.

And in either case I’d have to create a way to take money and start up some kind of entity and then do bookkeeping and report money things to the right places — all stuff I don’t have to waste time on right now. I can just work on the app.

Alternately I could create a web app that people would self-host — but there’s no way I could handle the constant support requests for installation issues. There are free self-hosted RSS readers already anyway, and NetNewsWire would be just another one. This also wouldn’t further my goal of making a free RSS reader available to everyone, since only people with the skills and willingness to self-host would do it.

Protecting Users

Second issue. Right now, if law enforcement comes to me and demands I turn over a given user’s subscriptions list, I can’t. Literally can’t. I don’t have an encrypted version, even — I have nothing at all. The list lives on their machine (iOS or macOS). If they use a syncing system, it lives there too — but I don’t run a syncing system. I don’t have that info and can’t get it.

If that happened, I’d have to pay a lawyer to see if the demand is legit and possibly help me fight it. That’s yet more money and time.

(Could I encrypt the subscription lists on the server? Yes, but the server would have to be able to decrypt it, or else the app couldn’t possibly work. Which means I could decrypt the lists and turn them over.)

Another type of freedom

Not an issue, exactly, but a thing.

I was 12 years old when I got my first computer, an Apple II Plus, and I’ve never stopped loving the freedom of having my own computer and being able to run whatever the hell I want to.

My computer is not a terminal. It’s a world I get to control, and I can use — and, especially, make — whatever I want. I’m not stuck using just what’s provided to me on some other machines elsewhere: I’m not dialing into a mainframe or doing the modern equivalent of using only websites that other people control.

A world where everything is on the web and nothing is on the machines that we own is a sad world where we’ve lost a core freedom.

I want to preserve that freedom. I like making apps that show the value of that freedom.

What I want to see happen is for Apple to allow iPhone and iPad users to load — not sideload, a term I detest, because it assumes Apple’s side of things — whatever apps they want to. Because those devices are computers.

I get it. It’s not looking good. And even with the much greater freedom for Mac apps there is still always the possibility of being shut down by Apple (by revoking developer memberships, refusing to notarize, or other technical means).

Still, though, I keep at it, because this freedom matters.

But, again…

Apple keeps doing things that make us all feel sick. Removing ICEBlock is just the latest and it won’t be the last. So I am sympathetic to the idea of making web apps, and my brain goes there more often. And if I could solve the problems of money and of protecting users, I’d be way more inclined.

Writing Mac and iOS Apps Shouldn’t Be So Difficult

In the ’90s and early 2000s I worked for UserLand Software — Dave Winer was founder and CEO — on a Mac app called UserLand Frontier.

The app was a scripting system and hash-table-oriented database that powered the early blogging and podcasting worlds. (That sounds grand, but it’s probably an understatement — but this post isn’t all about Frontier’s impact on the web, so I won’t go into details.)

The app was implemented in two pieces:

  • The kernel, written in C, implemented the database, networking, inter-application communication, various built-in data types, script compiler and evaluator and debugger, and so on
  • The scripts used the kernel and implemented most of the actual app behavior

Since it was an app, it had plenty of UI — menus, contextual menus, buttons, larger UI components, and so on. What was brilliant was that you could, for instance, add and edit menus, and when you chose a menu command it would run your script. (Or when you clicked a toolbar button, etc.)

You could write an entire static blog publishing system and the UI to go with it without ever restarting the app. Click a thing, then see what happens in the app — and if it’s not right you’d edit the script, which would be automatically recompiled when called the next time.

In other words, there was absolutely no friction when it came to iteration. Write some code without restarting and see your changes immediately.

How good was this really in practice?

You might imagine that we could do this for an hour or so before having to make changes to the kernel. Not so.

In fact, for the first three years I was there (might have been longer), I never even saw the kernel code. I worked all day every day as a professional developer at the script level, never having to restart the app. Just iterating like this all day long.

You might also imagine that the app was sluggish and slow since much of it was scripts instead of C code. It wasn’t! Scripts could be slow for the same reasons any code could be slow (I/O, of course, and algorithms and data structures not suited to the problem at hand) — but the app never felt slow.

I’ll remind you of the timing: this was the ’90s. We worked this way for real, and we were amazingly productive.

A scripting language plus key bits implemented in C was more than fast enough for an app. Even all those years ago.

A scripting language built for productivity

I’m not writing this article to praise Frontier — I’m talking about it to make a point, which I’ll get to.

But I wanted to bring up a second aspect to this: it’s not just frictionless iteration that was so great, it was also the scripting language and environment.

One of the best parts of this was how easy persistence was. I mentioned the hash-table-based database. Hash tables could contain hash tables (Swift developers: picture a Dictionary inside a Dictionary, and so on).

(We just called them tables for short — but remember that these are hash tables, not tables in a SQL database.)

In any script, at any time, without any ceremony, you could read and write from the database simply using dot notation: user.prefs.city = "Seattle" would set the value of city in the prefs table which was contained by the user table. This value would persist between runs of the app, because it was stored in the database.

(You could also pass around addresses of things too — it was quite common to pass the address of a table to another script, so that the other script wouldn’t need to hardcode a location.)

It was utterly automatic. And it meant that while we did have to choose where in the database to store things, and how to structure our storage, we didn’t have to choose a storage mechanism. It was the database.

(Note: of course we could read and write files, and did so when necessary. But the point is that the database handled almost all our persistence and in a super-easy way.)

(Also note: the database had a UI. It was visible and browsable. You could and often did hand-edit it. Even the scripts lived in the database, and were addressable via dot notation, like everything else.)

We had nice things!

I’ll say again — this was in the ’90s, more than 25 years ago, and it was a great way of working on an app.

I’m not saying apps these days need to be Frontier-like in any details. But it seems absolutely bizarre to me that we — we who write Mac and iOS apps — still have to build and run the app, make changes, build and run the app, and so on, all day long. In the year 2025.

And it seems retro in the worst way that we’re still using anything other than a scripting language for most of our code. We should be using something simple and light that can configure toolbars, handle networking callbacks, query databases, manage views, and so on. And maybe with a DSL for SwiftUI-like declarative UI.

Almost none of that code needs to be in a lower-level language like Swift or Objective-C. It really doesn’t. (I say this as a performance junkie!)

It could be in Ruby, Lua, Python, or JavaScript. Better still would be a new language invented specifically for the problem of writing apps, something designed to make the common challenges of app writing easier.

We did have this stuff decades ago. Not for app making in general, sure — but now it’s 25 years later, and a company like Apple could make this real for all its app makers.

It’s easy to see why things are the way they are right now, and you can point to a string of good decisions. No doubt.

But we can think outside of what we have now and ask: what would make app writing easier? What would make it a better experience? How could we get more done for our users with fewer bugs and faster turnaround?

I’m not saying that Frontier’s specific choices are the answer — I’m saying that the combination of frictionless iteration plus a purpose-built scripting language was extremely powerful, and we could use those things now.

And at some point I suspect these things are going to be table stakes for any platform that wants to attract developers. If you were a new developer right now, would you pick Xcode’s build-and-run, edit, build-and-run, edit — plus the growing complexity of Swift — over something like Electron and JavaScript?

Random notes

Yes, I know about PyObjc and RubyCocoa. Without first-class support in Apple’s developer tools, these were never going to work as popular alternatives.

I also know about (and use) Swift playgrounds and SwiftUI previews. Neither of these are as satisfying to use as I’d like, and neither of these are nearly as great as frictionless iteration in the actual app.

I also remember Xcode fix-and-continue, which didn’t work well enough to solve the problem of frictionless iteration.

Anyway… One more thing about Frontier: we had a system where people could get updates to the app automatically via the web. Those updates were just serialized versions of scripts at various database locations, which would get unpacked and stored in each user’s database. (Those who opted-in, of course.) The app would not have to be restarted to get bug fixes and new features! And of course the updates were very small, since they didn’t include the entire app. This seems so futuristic, but we had this in 1999. Why couldn’t we have this now?

Tough Season in the Apple Fields

We’re adopting Liquid Glass for NetNewsWire 7, which we’ll release some time after the new versions of macOS and iOS come out.

Stuart Breckenridge has been doing great work on getting this done — and he’s written up a couple blog posts (with screenshots!) on his progress. See:

Adopting Liquid Glass, Part II (NetNewsWire Mac)
Adopting Liquid Glass, Part III (NetNewsWire iOS)

Since the app is made with mostly stock Apple UI, you might think that using Liquid Glass would be very little work, that it might be pretty automatic or just a matter of checking a few boxes. But that’s not true this year: it’s been a fair amount of work.

Other apps, apps with more custom UI, will probably have even more work, but even for us it’s been more than a bit.

And we’re not done. There will be little things (hopefully just little things) still to do before shipping. Including verifying that it all works as expected on the actual OS releases.

But all credit to Stuart, who got right on this and did a superb job.

(Note: if you want to see the code, you can: it’s on our experimental/liquid-glass branch.)

But My Mac

As pleased as I am with Stuart’s work, I’m not pleased with Liquid Glass itself.

I don’t really care about it on iOS/iPadOS, because whatever. I don’t love those devices. I love Macs because it’s on Macs where you can set out to make new things that change the world.

(Okay. Fine. On iPhones and iPads you can, I guess, but generally it’s much harder, and it has to be an approved activity using an approved app. And one thing you definitely can’t do on those devices is create apps. [All apologies to people who do manage to edit their podcast episodes on an iPad or write at length on an iPhone. Cool! But I hope that even those folks will grant me my point.])

And so I seriously dislike the experience of using a Mac with Liquid Glass. The UI has become the star, but the drunken star, blurry, illegible, and physically unstable. It makes making things way more of a struggle than it used to be.

We had pretty good Mac UI, but Apple took the bad parts of it — the translucency and blurriness already there — and dialed it way up and called it content-centric. But it seems to me the opposite. Liquid Glass is Liquid-Glass-centric.

Perspective

First thing: I have many friends at Apple and I didn’t want to write any of this. And there are legions of engineers and designers who I don’t know but whose work I respect greatly. It’s not their fault that this is the direction of the UI.

And this is not the first time we’re going through a rough patch with Apple. I think of them as seasons — we had, for instance, terrible-keyboard season not so long ago. We were wondering if Apple would just stop making Macs altogether. But then that passed and we even got these wonderful Apple Silicon machines. Seasons end.

And we’re in a tough season with Swift these days too. It’s gotten so complex and difficult that I find myself daydreaming about going back to Objective-C. Objective-C is definitely funny-looking, but once you get past that it’s actually small and simple.

But with Swift approachable concurrency and other changes I can see eventually getting through this season and to a pretty great place, so I’m optimistic.

Seasons do end, in other words, or mostly seem to end (though not the App Store monopoly season, not so far), and I’ve resolved to just wait for Liquid Glass’s replacement. Perhaps along the way it will get refined enough so that people like me can use it without eye strain.

Better Perspective

But far, far worse than any of the above is Tim Cook’s gold statue presented to the President. And everything that went along with that. I felt utterly sick and I bet you did too. (And it made me seriously wonder if I wanted to continue writing apps for Apple platforms.)

I understand John Gruber’s argument in Gold, Frankincense, and Silicon that maybe Cook’s move was the best possible move in a terribly corrupted system.

But what’s the use of being so rich and so powerful, I would ask Tim Cook, if you, even more than regular people, have to debase yourself before the dictator?

It’s tempting to think that our current government is just a season, like the bad keyboards or like Liquid Glass will eventually prove to be. Wait till the mid-terms or the next presidential election, you might think.

But there’s no reason to think that this authoritarian turn is just a season. Something besides just wishing and waiting for better is required.

Breakpoints Show Thursday in Seattle

James Dempsey and the Breakpoints will be appearing in a Breakpoints Jam this Thursday (Aug. 21) at Bale Breaker in Ballard. Free show! Awesome songs!

The event starts at 6 pm and music will start around 7 pm. I’ll be on guitar — and you can expect local superstars Ken Case (keyboard, vocals) and Laura Savino (vocals) plus a special mystery guest or two from out of town.

The show will be mostly acoustic, and it will be outside at the picnic tables. I hope to see you there!

Saturday March

Tomorrow is No Kings. There’s one near you!

Chatting with my friends about how I hate these fascist assholes doesn’t do a damn thing. Protests work. (Imperfectly, sure, with no guarantees. But it sure beats not protesting.)

Retirement Day

I wrote in my love letter to my colleagues at Audible that retirement is coming up — and now it’s here. Today’s the day!

I’ve attended my last meetings. I’ve said my goodbyes. My laptop’s ready to ship back to Audible HQ.

* * *

I started working in 1984, while in high school, busing tables part time at Schaefers Canal House in Chesapeake City, MD.

And I stopped working this day in 2025, almost 41 years later, as a senior engineer (which is surprisingly a lot like busing tables — lots of cleanup and setting the table just right for the customers to have a great time).

Along the way I worked on, among other apps, Userland Frontier, NetNewsWire, MarsEdit, Glassboard, Vesper, OmniFocus, OmniOutliner, and Audible.

* * *

My immediate plan — Exhale! Breathe. Enjoy a steak. Watch WWDC from the comfort of home next week. Get back to work on NetNewsWire.

🌲

Retirement and NetNewsWire

To answer some questions people have asked me about my impending retirement…

What does it mean for NetNewsWire?

Good things! I’m not retiring from writing apps — which means I’ll have a lot more time for working on NetNewsWire.

It’s been 15 years since the last time I could work on NetNewsWire during weekdays (as opposed to just nights and weekends), and I’m super-psyched for this.

Will you work on any other apps?

Yes. I have several ideas for other apps I’d like to work on, and have made a little progress on one of them.

They will all be free and open source. I have no plans to create apps for money. (I’ll be retired — not working for money anymore is the point.)

Will you be taking a big trip right after retiring?

Every time this comes up, I joke that the first thing I’ll be doing is sleeping. Forty years of work is a long time, and I’ve earned a long nap.

We do have some travel plans, but no big trips yet. We will. There’s so much of the world we want to see!

My actual first week of retirement will be taken up by WWDC. I won’t be there — I’ll be at home watching the videos like most everyone else. Only this time I won’t have to think about how the changes will affect things at work.

Do you have any other hobbies or plans? Are you getting into woodworking? Pizza-making?

Yes to other hobbies and plans, though probably not woodworking or pizza (but never say never — those are pretty tempting ideas!).

Making apps is important to me — contributing to the public stack is how I can best use my abilities to make the world better — but it’s also not the only thing.

I have more ideas than time, which is a good problem to have, and once I have some space to think and feel I’ll be able to start picking and get to work.

Will you be blogging more?

I hope so!

The hard part is, after 25 years, finding things to say that I haven’t already said. Maybe I’ll just decide it’s okay to repeat myself in new ways. 🐥

My Wildly Incorrect Bias About Corporate Engineers

Before I went to work for Audible (five years ago now — time flies!) I had a bias about engineers that worked for large corporations. I assumed that they weren’t as good as indies and engineers at small companies, or else they’d actually be indies or work at small shops like Omni.

Obviously I knew there had to be exceptions, particularly at Apple, or else we wouldn’t have had great things like AppKit and UIKit and everything else we’ve built on over these years. But the bias persisted.

* * *

Before Audible, the largest company I’d ever worked at (Newsgator) had just over 100 people. When I worked at Omni it had roughly half that number.

I’ve spent half my career working at even smaller companies, with just me and Sheila (Ranchero Software) or at places with three people (Q Branch) or like six people (UserLand Software).

And of course I was arrogant enough to think that I was better — much better — than any corporate engineer. While a corporate engineer might own some small part of an app or framework — or just a single button, as the (lame) joke went back in the day — I was shipping entire apps on my own or with a very small team. Popular, valuable, newsworthy apps that people loved.

And I wasn’t the only one: think of Flying Meat, Rogue Amoeba, Bare Bones, Red Sweater, The Iconfactory and many more.

* * *

And so I learned very quickly when I started at Audible that I was very wrong. I was impressed, and grew more impressed as time went on, by my fellow engineers’ rigor, talent, professionalism, care, and, especially, ability to work with other people toward common goals.

While I’m the die-hard introvert who just wants to go into a room and sit in front of a Mac and write some code and get things done, I learned that my co-workers — even if they, like me, kinda just wanted to sit and write code — were great at app development as a team sport. I was impressed with how they wanted to grow and did grow — always leveling-up their individual skills and their ability to work on a team and across teams.

And what a team it was! It’s not a new observation, but the indies I mentioned above, and the ones I didn’t, tend to be white men born in the United States — the people who could most afford to fail, in other words, because for them (for me, absolutely) there’s always another opportunity.

My team didn’t look like that — it was quite a contrast with my previous experience. Many more women, people of color, people born outside the United States. (But note that there’s always more progress to be made!)

The engineers on my team could write apps as well, if not better in many cases, than the indies I know. And the ones who aren’t quite there yet — well, just give them a little more time. They’ve all given me reason to believe in them.

I regret my bias about engineers working in corporate environments, and I’m so glad I learned the truth almost from day one on starting at Audible.

* * *

For a couple years I did a lot of hiring — a lot of interviews — at Audible. And I noticed something: there was a strong correlation between being hirable and having worked with other people.

The folks who’d worked largely by themselves, or on just one small team, weren’t as good candidates as the folks who’d worked with more people. This, of course, went against my original bias that indies are the best engineers — but by then I knew that a candidate who’d worked with lots of other people had been exposed to more code, more dilemmas, more challenges (technical and human), and they were not just more ready to work on a larger team but more knowledgeable. Even their individual skills were greater.

Advice time: if you’re a newer engineer, find ways to work with other people. Not just because you’re more likely to get hired at a place like Audible — but because, no matter where you want to work, you’ll be better at it.

You can’t just sit alone in front of your computer all day and write code and expect to be a great engineer.

Lesson learned!

* * *

With retirement imminent — this is my last job, and June 6 is my last day (maybe I’ve buried the lede here) — I want to thank my team publicly for how they’ve made me a better engineer and, more importantly, a better person. From the bottom of my heart.

I learned more from them than I could ever have taught; I got the better part of this deal.

Thank you, team! So much. ❤️