Fardel runs on a laptop. There is no iPhone version, no Android version, and there is not going to be one.
For a long time I would have explained that as personal preference. A phone is not where I get anything done: I browse on it, take photos, read messages, look at social media. Everything I would call work happens on a laptop, including, slightly absurdly, posting to social media.
That explanation is true and it is not the reason. I found the actual reason while writing yesterday's post, which is that the argument I made there does not survive contact with a phone.
Mobile breaks the promise
The strongest thing I claimed for local-first is that your data outlives me. One SQLite file, an open format, readable by anything that speaks SQL, sitting on your disk whether or not I am still maintaining the project.
Notice how much of that sentence depends on the words "on your disk."
On a desktop that is literal. There is a path. You can open the folder, see the file, copy it to a USB stick, open it in another tool, back it up with whatever you already use, and hand it to a different program in ten years. The file is an object in a filesystem you control.
On iOS and Android it is not. An app's data lives in a container belonging to the app. It is not browsable by default, it is not somewhere you can point another program at, and the platform decides what, if anything, is exposed to a file picker. Delete the app and the container goes with it.
What you get instead is an export button, if the developer wrote one. Which means your data is not yours in the sense I was arguing for. It is the app's, and you have been granted a means of requesting a copy in a shape the developer chose. That is exactly the relationship with a cloud service, minus the server, and it fails in exactly the same way when the software stops being maintained.
So "local-first mobile app" is doing something, but it is not doing the thing I care about. It gives you offline access and low latency. It does not give you custody. The durability argument, the one I said was decisive, quietly evaporates.
The gatekeeper problem
Suppose I wanted to ship it anyway. To put software on an iPhone I need a developer account with an annual fee, a review process, and compliance with rules I do not write and cannot appeal in any meaningful sense. The store can reject the app. The store can remove it later.
I have spent the last several days writing about not wanting my infrastructure to depend on companies whose incentives are not mine. Shipping a privacy-motivated app through a gatekeeper that can delete it from every device at once would be an odd way to end that sequence of posts.
There are alternatives. Android allows sideloading, and iOS has been prised partly open in the EU. But these are the exceptions you reach for after accepting that the normal path is asking permission. On a desktop there is no normal path to ask permission on. I put the code somewhere and you run it.
One person, two platforms
There is a boring reason too, and it deserves saying because it is probably the one that actually decides most projects.
Mobile is two platforms, in two languages, with two sets of platform conventions, two review processes, and a compliance surface that keeps moving. Either that or a cross-platform framework, which is one more dependency between me and the thing I am trying to build.
I am one person who writes this in the evenings. Going mobile means most of my budget goes on distribution rather than on the app, and I would rather the app be good than available in more places while being worse.
The stack is the same decision
Fardel is Elixir and Phoenix LiveView. When you run it, it starts a web server listening on localhost:4649, and you use it in the browser you already have open.
That is a strange-sounding architecture until you notice what it removes. There is no packaging, no installer, no code signing, no notarisation, no update mechanism, no store listing, and no native UI toolkit to fight. The interface is HTML, the database is a file, and the whole thing is a mix phx.server away from running.
None of that is available to me on a phone. You cannot run a local web server as your app on iOS in any way that resembles a normal user experience. The moment I target mobile, I lose the architecture that made the project small enough for one person to finish.
So the desktop decision and the stack decision are not two decisions. Choosing a local file and a local server chose the platform, and the platform is the one where local files and local servers are ordinary things rather than special dispensations.
What it costs, briefly
I listed the price yesterday and I will not relitigate it, except for the part that lands hardest here: a finance app is exactly the kind of thing people want in a shop, and mine is at home on a laptop. That is a real loss and I do not have a clever answer to it.
What I have is an ordering. Being able to check a balance while standing in a queue is convenience. Being able to open my own records in twenty years without anyone's cooperation is custody. When those two conflict, I would rather keep the second, and mobile platforms are built such that keeping the second is not on the menu.
The honest summary
I build for the desktop because I do not work on a phone. That is where it started, and I am not going to pretend I derived it from first principles. I had the conclusion for about two years and only went looking for the argument this week.
It turned out to be load-bearing anyway, which I am choosing to file under instinct rather than luck.
A phone is a machine you use. A laptop is a machine you own, in the one sense that matters here: there is a folder, and the things you put in it are yours. That is the entire bar. Not encryption, not a manifesto, not a bill of rights for users. A folder, with your file in it, that you can open. It is a humiliating bar to have to state out loud, and the industry has spent the better part of two decades learning to limbo under it.