How Seekquel gets built, and why it ships so often

Seekquel adds features most weeks, which usually reads as a warning sign. Here is the year of quiet groundwork behind it, the two people who build it, and the readers who steer it.

A reader put a polite question to me recently. Was I building Seekquel too fast? New things keep turning up in the app, and that usually reads as a warning sign. An app that changes every week is often an app that breaks every week.

Fair question, and the answer starts about a year before the first update any of you saw.

The first year had nothing to show for it

Before Seekquel was something you could open, it was mostly planning. Which features belonged together, what they would need from each other, and what order to build them in. Get that wrong and the later features force a rewrite of the earlier ones.

Then I built it one block at a time, slower than I wanted to. One rule held the whole way, and it annoyed me plenty. If two parts of the app need the same thing, they use the same thing. Not a copy of it. The same one.

That year produced almost nothing anyone could look at. It is the whole reason the pace looks the way it does now.

Much of what arrives this month was finished months ago

This is the part that surprises people. Plenty of what shows up in an update is old work. Some of it predates the first public release. A small group of testers had been using it daily the whole time, and they knew it was rough.

So "shipped this week" usually means something narrower. It means the work finished a while back. A handful of people have used it daily since, hitting the sharp edges so I could file them off. This week it went on for everyone.

We can open a feature to a few testers first and to everyone later. Nobody downloads a new version for it. The app on your phone has often been running a feature for weeks before you see it.

What building block by block bought

A few examples of the pattern. These are not a catalogue of the app. They are the clearest examples of why a new feature rarely starts from nothing.

Some screens take their shape from the server. The filters on your library work this way. The app does not ship knowing what the filters are. The server describes them, and the screen draws what it gets. Adding a new way to filter is a change on our side. It turns up inside the filter sheet you already know. Web, Android and iOS at once, in every language the app speaks.

Some things live in a table instead of in the app. Badges are one. Their names, their tiers and the numbers you have to reach are rows we can edit. If a threshold is too harsh, or the wording confuses people, it changes the same day. You do not need an app update to see it.

Outside services plug into a standard socket. Book data, covers, the e-reader integrations, payments. None of them sit directly inside the app. When one provider went unreachable in August, nothing else needed a rewrite. Nothing else knew which provider it was.

We share the visible pieces too, and the panels that slide up from the bottom are the obvious case. They are all the same panel. We fixed how it behaves as the keyboard opens, and that fix landed on every screen at once. Screens I wrote months later included.

We reuse behaviours instead of rebuilding them. Selecting a batch of books and acting on all of them took one solve. Bringing it to another screen is wiring rather than building.

None of that is the interesting part of an app. It is why the interesting parts arrive fast, built out of pieces already in use for months.

Two of us, and quite a few of you

Seekquel is mostly two people. I write the code and do the design. My wife tests everything and breaks it in ways that would never occur to me. She also brings a steady stream of ideas and small corrections. The app is better for it than the one I would have built alone. A good number of the features you use started as something she said over dinner.

Friends test on real devices before a release, because a simulator never shows you what a real device does. It matters most on the e-reader side, where every device is strange in its own way. Several of them have lived with unfinished features for months. The version you get is the one that works.

Then there is the community, which decides much of the order. The feedback board takes votes, and I work down it rather than down my own list. Book requests come in through the app, and I add them. Testers see things weeks early and tell me what is wrong while it is still cheap to change.

And the librarians, readers who fell for the app and started repairing the catalogue themselves. Wrong covers, missing series entries, descriptions attached to the wrong book. They fix it directly, and a great deal of the catalogue quality you see is theirs rather than mine. If you have ever wondered whether posting on the feedback board does anything: it decides what I build next.

When something does break

Things still break. When they do, we can switch off the one feature involved within minutes. There is no app store review to wait for. Everything around it keeps working, because nothing else leans on it.

The caveat is that not everything moves at this speed. Anything touching the reading experience is slow, and so is anything needing a fresh version through the app stores. That will stay slow. When something is going to take weeks, I would rather say so than let it sit quietly.

So the pace is not corner cutting. It rests on a year of unglamorous groundwork, and on people who were here before the app was public. The rest of it is a queue of requests I am working through in the order you voted for.