{
    "archive_path": "archive/1787688747.504509",
    "base_url": "www.flourish.org/2026/08/personal-apps",
    "basename": "",
    "bookmarked_date": "2026-08-25 20:12",
    "canonical": {
        "archive_org_path": "https://web.archive.org/web/www.flourish.org/2026/08/personal-apps",
        "dom_path": "output.html",
        "favicon_path": "favicon.ico",
        "git_path": "git/",
        "google_favicon_path": "https://www.google.com/s2/favicons?domain=www.flourish.org",
        "headers_path": "headers.json",
        "htmltotext_path": "htmltotext.txt",
        "index_path": "index.html",
        "media_path": "media/",
        "mercury_path": "mercury/content.html",
        "pdf_path": "output.pdf",
        "readability_path": "readability/content.html",
        "screenshot_path": "screenshot.png",
        "singlefile_path": "singlefile.html",
        "warc_path": "warc/",
        "wget_path": "www.flourish.org/2026/08/personal-apps/index.html"
    },
    "domain": "www.flourish.org",
    "extension": "",
    "hash": "16E6AHBNG6VHPVPYMQJQ",
    "history": {
        "archive_org": [],
        "dom": [],
        "favicon": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "60",
                    "--output",
                    "favicon.ico",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://www.google.com/s2/favicons?domain=www.flourish.org"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-08-25T20:16:07.125381+00:00",
                "index_texts": null,
                "output": "favicon.ico",
                "pwd": "/data/archive/1787688747.504509",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-25T20:16:06.578282+00:00",
                "status": "succeeded"
            }
        ],
        "git": [],
        "headers": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--head",
                    "--max-time",
                    "60",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://www.flourish.org/2026/08/personal-apps/"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-08-25T20:16:07.807626+00:00",
                "index_texts": null,
                "output": "headers.json",
                "pwd": "/data/archive/1787688747.504509",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-25T20:16:07.131903+00:00",
                "status": "succeeded"
            }
        ],
        "htmltotext": [],
        "media": [],
        "mercury": [
            {
                "cmd": [
                    "/app/node_modules/@postlight/parser/cli.js",
                    "https://www.flourish.org/2026/08/personal-apps/"
                ],
                "cmd_version": "1.0.0",
                "end_ts": "2026-08-25T20:16:16.703368+00:00",
                "index_texts": null,
                "output": "mercury",
                "pwd": "/data/archive/1787688747.504509",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-25T20:16:13.123081+00:00",
                "status": "succeeded"
            }
        ],
        "pdf": [],
        "readability": [
            {
                "cmd": [
                    "/app/node_modules/readability-extractor/readability-extractor",
                    "/tmp/tmpuyv3po7p",
                    "https://www.flourish.org/2026/08/personal-apps/"
                ],
                "cmd_version": "0.0.11",
                "end_ts": "2026-08-25T20:16:13.116306+00:00",
                "index_texts": [
                    "There are a few mobile apps that I\u2019ve wanted for a while, and that are relatively\nspeaking just for me.\nToucan Music showing artwork\n\n\nPlaces - When people recommend restaurants or cafes to me, I\u2019ve for a long time put them in\na Google Maps list. It\u2019s annoying in various ways, for example the page zooms out when you\nselect the list. And I don\u2019t like keeping my data locked into a free service.\n\n\nPeople - I\u2019m face blind, and struggle to remember people I haven\u2019t met quite a few times.\nThis is especially noticeable networking in a metropolis. The idea is to help me\nremember who people are, and train me with spaced repetition to learn their faces.\n\n\nMusic - This one I made impulsively in the last week. Like many others, I\u2019ve\nlong wanted to organise\nalbums in folders on Spotify. After a quest to switch back to buying MP3s, which failed\nbecause it got too complicated, I made a custom Spotify player instead.\n\n\nSo over the last month or so I vibe coded Toucan\n(choose \u201clocal only\u201d to just play with it, any data you put in will stay in your browser).\nFor what it is worth, the source code is here.\nBut I\u2019m not really proud enough of it to say it is a \u201crelease\u201d - more on that below.\nArchitecture\nThe apps I describe above need to work on mobile and sync data to web to use them on\ndesktop. The usual way of doing this would be to make your own personal\nsoftware-as-a-service with its own web server and database, and then also a mobile app.\nThis felt a bit much - clunky, excessive and not very scalable. I\u2019ve\nlong been a fan of what is now called the local-first software movement.\nThe idea is that data is primarily on each device, with a standardised sync server to get it\nbetween them. This makes operations extremely fast, as they just act locally. Syncing\nhappens in the background. Think something a bit like Dropbox, but for data in databases.\nSome of the data is quite private - particularly people\u2019s faces, but even their names on\nrestaurant recommendations. So I prefer syncing to my own server hosted at an\nexcellent local ISP.\nI was disappointed to find there isn\u2019t standard personal data sync server software - I was\nhoping for something at least as modestly popular as Nextcloud.\nWhich you likely haven\u2019t heard of, but is a self-hosted file syncing server (and more).\nIn the end Fable and I went for Yjs which is the most popular\nlocal-first protocol. I wanted a simple server that just writes to a SQLite database (so I\ncould do hosting and backups very easily). Fable found the obscure\nHocuspocus, which is simple and does\nthe job (alas it turned out its format is opaque and binary inside the database file, but\nthat\u2019s another story).\nI spent a while wondering if I could write the UI in Rust but\nin the end went for simple and made a Javascript progressive web app (PWA).\nWhen installed on my Android phone (via Chrome, for some reason it doesn\u2019t work in Firefox), it is just as good as an actual app. The web version and the mobile version are the same code\nand work just the same. Even with LLM coding agents, that saves a lot of hassle.\nBasic process\nToucan Places at a coffee shop\nI did most of this on the \u00a318/month Claude plan, using mostly Opus. Fable helped with a\nbunch of initial planning, but I\u2019m not sure it made a lot of difference. Several of\nthose decisions were bad anyway, and were refactored later.\nMy processes are commonplace by this point in LLM coding. There\u2019s a plans/ directory\nwhere anything large gets designed first. I edit it, make decisions, then clear the\ncontext window and tell the agent to implement the plan.\nIf something is a significant UX or design change, I ask Claude to make an artefact with\ndifferent options for the design in it. These are surprisingly high quality, especially\nafter a few iterations.\nI manage bugs and tasks in a simple to-do file.\nThe agent ticks them off when it has done them, then I QA them and delete them.\nMost of these tasks are under a heading \u201cPolish\u201d. That\u2019s because I have to give a lot of\nproduct and UX detailed feedback. I take note of them while I\u2019m using the apps as I go\nabout my day. Dozens and dozens of items for each app. This is a major reason I think this\nis hard to scale to anyone right now - see below.\nI\u2019m stubbornly not upgrading to a more expensive AI coding plan. I\u2019ve lots of other things\nto do, and quite liked being stopped by the 5 hour window, as this is addictive.\nLater on I learnt you can type !sleep 3h (or whatever) when you run out of tokens, and\npress Ctrl+B to background it (otherwise you get a 2 minute timeout). Claude will wake up\nhours later, and carry on with its limits reset, even if I\u2019m not around.\nMaking it do a good job\nBespoke snapshot testing tool\nIt\u2019s the case with LLM coding that things which have long been good practice become even\nmore valuable. Such as strictly configured type checking and 100% test coverage - see\nJonathan Lange\u2019s Galahad Principle\nfor why \u201c100\u201d is especially magical.\nThese give the agents basic feedback loops, which they are now reasonably good at\nresponding sensibly to. They won\u2019t, however, set up things like that if you don\u2019t ask them to. Yet.\nI managed and coded on a front-end development team\nfor some years, and although we did lots of good things, we never quite got to snapshot\ntesting. And I\u2019ve always wanted to do it.\nSo, quite early on, Claude created a tool for Toucan that uses a headless browser to take a screenshot of\nevery page of the application. This is really good, partly as an integration test, partly\nso it can check designs, and partly so I can QA designs. There\u2019s a web view for me (JSON\nfor the LLM), an integrated pixel diff, lots of filter and view options, basic performance\nmeasurements, and command line switches to snapshot against another branch.\nThis was invaluable.\nThe end result is that almost anything I ask the agent to do \u2026 It just does. It\nusually makes some aesthetic choices I don\u2019t like, or messes up part of the UX.\nSometimes I have to argue with it about data structures, or choices of where in the\nsystem to cache things.\nBut generally, it codes the thing. It doesn\u2019t break anything else. The existing tests\npass, new ones are added. It is working at the level of a super fast senior software\nengineer, albeit one with poor contextual awareness. For that wait until late 2027 or 2028.\nLast year, I didn\u2019t in my soul think it\u2019d get this good at coding.\nI had one serious bug. I\u2019d never tested a new feature to reorder lists, and pressed\nit on my phone while out. It deleted the list completely and everything in it! The bug\nwas not doing the array manipulation correctly for the local first storage engine.\nThe agent helped me recover the data, add various logging features to be able to\nsee what is happening with syncing, and update documentation to make it clear not to\nmake the same mistake again.\nFinally, following Jyn\u2019s advice, I added a self improvement\nfeedback loop. My version is fairly dumb - a prompt in AGENTS.md to tell it to write\nanything that caused it difficulty into SELF-IMPROVE.md and\nkeep a count of how often the same problem shows up. I then look at that, see what\nmakes sense, and schedule improvements.\nThis found things like visually unstable snapshots, churn in node_modules that it would\ntry and work round repeatedly, performance problems, missing tools and so on. It feels\nvery primitive, but I expect we\u2019ll all spend a lot of time supervising this kind of\nthing in the coming years. \u201cAI developer\nexperience\u201d.\nRefactoring\nIdeology for international standards and simplicity drove me to try and use web components\nand plain Javascript. I was hoping the Toucan platform could be itself so powerful, that\nthe apps would be quite short, single HTML files. It didn\u2019t work out, and eventually I\nrealised that the code was getting messy, and that build steps are cheap and easy with an\nLLM anyway, so we did two large refactors.\nOne was to Typescript, the other to Preact (a lighter weight React). They both went well -\nthe snapshots helped make sure nothing broke, and nothing indeed broke. Everything pixel\nperfect the same after refactoring. I haven\u2019t, though, spent much time manually checking\ncode quality - see next section.\nThe initial graphical design was quite ropey. It took a lot of forcefulness to get it to\nupgrade it, but it was possible. I had to force it to make shared components properly.\nSomeone with more design skills than me could make it really good. Compared though to what\nI would make by myself, excellent.\nFuture\nThree full on mobile apps, with desktop versions. It\u2019s frankly amazing it is possible to\nmake them with such little effort, and so polished.\nThey\u2019re dangerously close to something other people could use. If I\u2019d written these 5\nyears ago, I\u2019d definitely be marketing them and trying to get users.\nRight now though that feels slightly \u2026 exhausting? They\u2019re a bit too vibe coded to\nme. A touch eccentric to install and set up. Slightly too specific in what they do.\nThe open question for me is, how can big collaborative open source projects be run in a\nworld of agents coding? What I really want is to make it easy for anyone to make their own\ncustom, stateful, syncing apps. This feels tricky for the following reasons:\n\n\nUX and product feedback is a skill, and still hard to do. Expectations on mobile are\nhigh, and I think few people will go through the feedback necessary.\n\n\nFrameworks for cross-platform apps are still quite clunky. The widget sets that look good\non web and mobile are limited, PWAs aren\u2019t familiar to end users, coding multiple\napps is specialist and hard to deploy.\n\n\nI don\u2019t truly feel like I own the product. This would be less of a worry if I was\nrunning a business. But I haven\u2019t closely scrutinised the code - I didn\u2019t need to. What\nare people\u2019s expectations for open source in this world? How do we communicate it is\nsomething of quality that will be maintained? I\u2019m so used to the code being a key\nthing being shipped in open source.\n\n\nLocal-first doesn\u2019t have a standardised platform. I can imagine a world where it was\nas normal as having an email address, to have a personal data store that can sync local\nfirst. But it isn\u2019t. It isn\u2019t clear how to do the work that might make that happen in\n2026 - just developing it isn\u2019t a strong status signal any more.\n\n\nHow do you think large, open projects will be developed with LLMs, such that they really\nbenefit users?"
                ],
                "output": "readability",
                "pwd": "/data/archive/1787688747.504509",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-25T20:16:11.734171+00:00",
                "status": "succeeded"
            }
        ],
        "screenshot": [],
        "singlefile": [],
        "title": [
            {
                "cmd": [
                    "curl",
                    "--silent",
                    "--location",
                    "--compressed",
                    "--max-time",
                    "60",
                    "--user-agent",
                    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) curl/curl 8.14.1 (x86_64-pc-linux-gnu)",
                    "https://www.flourish.org/2026/08/personal-apps/"
                ],
                "cmd_version": "curl 8.14.1 (x86_64-pc-linux-gnu)",
                "end_ts": "2026-08-25T20:16:11.729471+00:00",
                "index_texts": null,
                "output": "Vibe coding personal apps in mid-2026 - Francis Irving",
                "pwd": "/data/archive/1787688747.504509",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-25T20:16:11.720939+00:00",
                "status": "succeeded"
            }
        ],
        "wget": [
            {
                "cmd": [
                    "wget",
                    "--no-verbose",
                    "--adjust-extension",
                    "--convert-links",
                    "--force-directories",
                    "--backup-converted",
                    "--span-hosts",
                    "--no-parent",
                    "-e",
                    "robots=off",
                    "--timeout=60",
                    "--restrict-file-names=windows",
                    "--warc-file=/data/archive/1787688747.504509/warc/1787688967",
                    "--page-requisites",
                    "--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 ArchiveBox/0.7.4 (+https://github.com/ArchiveBox/ArchiveBox/) wget/GNU Wget 1.21.3",
                    "--compression=auto",
                    "https://www.flourish.org/2026/08/personal-apps/"
                ],
                "cmd_version": "GNU Wget 1.21.3",
                "end_ts": "2026-08-25T20:16:11.714961+00:00",
                "index_texts": null,
                "output": "www.flourish.org/2026/08/personal-apps/index.html",
                "pwd": "/data/archive/1787688747.504509",
                "schema": "ArchiveResult",
                "start_ts": "2026-08-25T20:16:07.815232+00:00",
                "status": "succeeded"
            }
        ]
    },
    "icons": null,
    "is_archived": true,
    "is_static": false,
    "latest": {
        "archive_org": null,
        "dom": null,
        "favicon": "favicon.ico",
        "git": null,
        "media": null,
        "pdf": null,
        "screenshot": null,
        "singlefile": null,
        "title": "Vibe coding personal apps in mid-2026 - Francis Irving",
        "warc": null,
        "wget": "www.flourish.org/2026/08/personal-apps/index.html"
    },
    "link_dir": "/data/archive/1787688747.504509",
    "newest_archive_date": "2026-08-25T20:16:13.123081+00:00",
    "num_failures": 0,
    "num_outputs": 6,
    "oldest_archive_date": "2026-08-25T20:16:06.578282+00:00",
    "path": "/2026/08/personal-apps/",
    "schema": "Link",
    "scheme": "https",
    "snapshot_id": "df64ed85-7723-4399-978c-8f7b39721f32",
    "sources": [
        "/data/sources/1787688747-import.txt"
    ],
    "tags": null,
    "tags_str": "",
    "timestamp": "1787688747.504509",
    "title": "Vibe coding personal apps in mid-2026 - Francis Irving",
    "updated": "2026-08-25T20:16:06.577513+00:00",
    "updated_date": "2026-08-25 20:16",
    "url": "https://www.flourish.org/2026/08/personal-apps/"
}