There are a few mobile apps that I’ve wanted for a while, and that are relatively speaking just for me.
-
Places - When people recommend restaurants or cafes to me, I’ve for a long time put them in a Google Maps list. It’s annoying in various ways, for example the page zooms out when you select the list. And I don’t like keeping my data locked into a free service.
-
People - I’m face blind, and struggle to remember people I haven’t met quite a few times. This is especially noticeable networking in a metropolis. The idea is to help me remember who people are, and train me with spaced repetition to learn their faces.
-
Music - This one I made impulsively in the last week. Like many others, I’ve long wanted to organise albums in folders on Spotify. After a quest to switch back to buying MP3s, which failed because it got too complicated, I made a custom Spotify player instead.
So over the last month or so I vibe coded Toucan (choose “local only” to just play with it, any data you put in will stay in your browser). For what it is worth, the source code is here. But I’m not really proud enough of it to say it is a “release” - more on that below.
Architecture
The apps I describe above need to work on mobile and sync data to web to use them on desktop. The usual way of doing this would be to make your own personal software-as-a-service with its own web server and database, and then also a mobile app.
This felt a bit much - clunky, excessive and not very scalable. I’ve long been a fan of what is now called the local-first software movement. The idea is that data is primarily on each device, with a standardised sync server to get it between them. This makes operations extremely fast, as they just act locally. Syncing happens in the background. Think something a bit like Dropbox, but for data in databases.
Some of the data is quite private - particularly people’s faces, but even their names on restaurant recommendations. So I prefer syncing to my own server hosted at an excellent local ISP.
I was disappointed to find there isn’t standard personal data sync server software - I was hoping for something at least as modestly popular as Nextcloud. Which you likely haven’t heard of, but is a self-hosted file syncing server (and more).
In the end Fable and I went for Yjs which is the most popular local-first protocol. I wanted a simple server that just writes to a SQLite database (so I could do hosting and backups very easily). Fable found the obscure Hocuspocus, which is simple and does the job (alas it turned out its format is opaque and binary inside the database file, but that’s another story).
I spent a while wondering if I could write the UI in Rust but in the end went for simple and made a Javascript progressive web app (PWA). When installed on my Android phone (via Chrome, for some reason it doesn’t work in Firefox), it is just as good as an actual app. The web version and the mobile version are the same code and work just the same. Even with LLM coding agents, that saves a lot of hassle.
Basic process
I did most of this on the £18/month Claude plan, using mostly Opus. Fable helped with a bunch of initial planning, but I’m not sure it made a lot of difference. Several of those decisions were bad anyway, and were refactored later.
My processes are common place by this point in LLM coding. There’s a plans/ directory
where anything large gets designed first. I edit it, make decisions, then clear the
context window and tell the agent to implement the plan.
If something is a significant UX or design change, I ask Claude to make an artefact with different options for the design in it. These are surprisingly high quality, especially after a few iterations.
I manage bugs and tasks in a simple to-do file. The agent ticks them off when it has done them, then I QA them and delete them.
Most of these tasks are under a heading “Polish”. That’s because I have to give a lot of product and UX detailed feedback. I take note of them while I’m using the apps as I go about my day. Dozens and dozens of items for each app. This is a major reason I think this is hard to scale to anyone right now - see below.
I’m stubbornly not upgrading to a more expensive AI coding plan. I’ve lots of other things
to do, and quite liked being stopped by the 5 hour window, as this is addictive.
Later on I learnt you can type !sleep 3h (or whatever) when you run out of tokens, and
press Ctrl+B to background it (otherwise you get a 2 minute timeout). Claude will wake up
hours later, and carry on with its limits reset, even if I’m not around.
Making it do a good job
It’s the case with LLM coding that things which have long been good practice become even more valuable. Such as strictly configured type checking and 100% test coverage - see Jonathan Lange’s Galahad Principle for why “100” is especially magical.
These give the agents basic feedback loops, which they are now reasonably good at responding sensibly to. They won’t, however, set up things like that if you don’t ask them to. Yet.
I managed and coded on a front-end development team for some years, and although we did lots of good things, we never quite got to snapshot testing. And I’ve always wanted to do it.
So, quite early on, Claude created a tool for Toucan that uses a headless browser to take a screenshot of every page of the application. This is really good, partly as an integration test, partly so it can check designs, and partly so I can QA designs. There’s a web view for me (JSON for the LLM), an integrated pixel diff, lots of filter and view options, basic performance measurements, and command line switches to snapshot against another branch.
This was invaluable.
The end result is that almost anything I ask the agent to do … It just does. It usually makes some aesthetic choices I don’t like, or messes up part of the UX. Sometimes I have to argue with it about data structures, or choices of where in the system to cache things.
But generally, it codes the thing. It doesn’t break anything else. The existing tests pass, new ones are added. It is working at the level of a super fast senior software engineer, albeit one with poor contextual awareness. For that wait until late 2027 or 2028. Last year, I didn’t in my soul think it’d get this good at coding.
I had one serious bug. I’d never tested a new feature to reorder lists, and pressed it on my phone while out. It deleted the list completely and everything in it! The bug was not doing the array manipulation correctly for the local first storage engine. The agent helped me recover the data, add various logging features to be able to see what is happening with syncing, and update documentation to make it clear not to make the same mistake again.
Finally, following Jyn’s advice, I added a self improvement
feedback loop. My version is fairly dumb - a prompt in AGENTS.md to tell it to write
anything that caused it difficulty into SELF-IMPROVE.md and
keep a count of how often the same problem shows up. I then look at that, see what
makes sense, and schedule improvements.
This found things like visually unstable snapshots, churn in node_modules that it would
try and work round repeatedly, performance problems, missing tools and so on. It feels
very primitive, but I expect we’ll all spend a lot of time superivising this kind of
thing in the coming years. “AI developer
experience”.
Refactoring
Ideology for international standards and simplicity drove me to try and use web components and plain Javascript. I was hoping the Toucan platform could be itself so powerful, that the apps would be quite short, single HTML files. It didn’t work out, and eventually I realised that the code was getting messy, and that build steps are cheap and easy with an LLM anyway, so we did two large refactors.
One was to Typescript, the other to Preact (a lighter weight React). They both went well - the snapshots helped make sure nothing broke, and nothing indeed broke. Everything pixel perfect the same after refactoring. I haven’t, though, spent much time manually checking code quality - see next section.
The initial graphical design was quite ropey. It took a lot of forcefulness to get it to upgrade it, but it was possible. I had to force it to make shared components properly. Someone with more design skills than me could make it really good. Compared though to what I would make by myself, excellent.
Future
Three full on mobile apps, with desktop versions, feels dangerously close to something other people could use. If I’d written these even 5 years ago, I’d definitely be marketing them and trying to get users.
Right now though that feels slightly … exhausting? They’re a bit too vibe coded to me. A touch eccentric to install and set up. Slightly too specific in what they do.
It’s an open question to me are how big collaborative open source projects happen now. What I really want is to make it easy for anyone to make their own custom, stateful, syncing apps. This feels tricky for the following reasons:
-
UX and product feedback is a skill, and still hard to do. Expectations on mobile are high, and I think few people will go through the feedback necessary.
-
Platforms for cross-platform apps are still quite clunky. The widget sets that look good on web and mobile are limited, PWAs aren’t familiar to end users, coding multiple apps is specialist and hard to deploy.
-
I don’t truly feel like I own the product. This would be less of a worry if I was running a business. But I haven’t closely scrutinised the code - I didn’t need to. What are people’s expectations for open source in this world? How do we communicate it is something of quality that will be maintained? I’m so used to the code being a key thing being shipped in open source.
-
Local-first doesn’t have a standardised platform. I can imagine a world where it was as normal as having an email address, to have a personal data store that can sync local first. But it isn’t. It isn’t clear how to do the work that might make that happen in 2026 - just developing it isn’t a strong status signal any more.
How do you think large, open projects will be developed with LLMs, such that they really benefit users?


