My own everything app
This one started as a continuation of Grocery Shopping. That little app worked so well for us that I started thinking, why not expand it with more small modules and replace some of the other apps I use every day? Also I love self hosting and the whole homelab thing, so the idea of having all of that running on my own servers was very attractive.
The shape of it
So I made a modular personal hub:
- One small kernel, written in Python, that lives on my server, with everything stored in a single SQLite file.
- Three surfaces: the TUI, the mobile app, and the webapp (I love TUIs, mostly for ergonomics reasons, as I wrote in On computer ergonomics).
- Sixteen modules: RSS, todo, wiki, groceries, habits, thoughts, and so on. Which is not as impressive as it sounds, since the LLMs do most of the work nowadays.
- Very modular and extendable: a new module plugs into the kernel and shows up on every surface.
- An optional agent, that can talk with me and operate the modules.
An agent on top, not instead
I did not want this to be just an agent, and that is on purpose. I still believe that for many tasks a consistent, predictable UI is much better than a conversation: ticking off the groceries in the supermarket, or skimming the feeds, should always look the same and be one tap away. So every module got its own small UI first, and the agent came much later, on top of them.
The agent works in two ways:
- On its own, in Chat, where via tool calling it can reach into all the other modules. This is where it gets really fun: I can say "create a wiki entry about Wanza Mian (a noodle dish from Chongqing), and add the ingredients to the grocery shopping module" and it just does it.
- Inside the modules, doing the small things: summarizing an RSS item, reorganizing the grocery list, etc.
Here it is during a study check-in, pinning my Learning Japanese wiki page to the conversation as a bubble:
Building it
I think the most important thing was getting the initial architecture right, so things can be built without constant fighting. Contracts between the kernel and the modules are very important, and tests too: they make sure new code does not break the previous things. That was already important before, but in the LLM era even more, because it is another layer of trust we can add on top of the generated code.
Another thing I practice is not blindly generating code and using it. I try to keep an updated mental model of the code, so I always tell the LLMs to keep a technical manual and a user manual updated. Skimming through the technical manual is a great way to know what is going on under the hood.