How I replaced Obsidian and Emacs Org-mode with localStorage
Multi-purpose productivity apps like Obsidian and Org-mode have endless flexibility, one might argue they are too flexible. This post explores why personal tools work best when they’re purpose-built, and how AI makes it easy to build your own apps that do one thing well.
Admin
July 23, 2025
I have been (and still am) a big fan of Obsidian, Notion, Emacs Org-Mode and other multi-purpose productivity apps. They are so flexible that you can do almost anything with them! ... I have also found that their flexibility is their biggest downside.
Multi-purpose vs single-purpose?
If you have ever used Obsidian or Emacs Org-mode, chances are that you ended up trying to use it for everything - note taking, day planning, gym routine tracking, personal finance and the list goes on. I have found that Obsidian and Org-mode are really good for note taking. And that's it. That's where it should stop. Everything I’ve tried to make it work for other purposes has always felt like a hack.
- "Oh sure, I don't mind using a text editor with my thumbs on my phone to fill out my reps in the gym, it's not hard at all".
- "I don't mind that Org-mode is not really available on the phone. I only take notes in front of my PC"
- "Data synchronization? Ever heard of github?"
- "I just have to learn a new DSL to query data in the format I want? That's awesome!"
I was lying to myself, which explained why I would use these tools for a month and then abandon them again. I simply didn't want to accept that I needed separate tools that do one thing well. Partially because most of the existing tools didn't work the way I wanted them to work. The problem again was complexity. Even the simplest personal finance app needs to appeal to a wide audience and thus has a lot of unnecessary features.
What should I do?
Personal apps should be personal. The only way for them to be personal is to make them yourself. As a programmer, for most of my career this has been theoretically possible, but not practically. As much as I wanted good personal tools, I did not want to spend all my time on "meta" work.
Things are different now and I think you already know why. Drumroll... AI. Yep, in one afternoon, I could generate a web app for gym tracking that worked exactly as I wanted it to work.
I don't want to deal with hosting apps
That was my first thought when I realized I could build a custom solution for all my needs. I mean, I don't mind spinning up a VPS and setting it up once. But to do it for every single app I might want to create is too much work. I needed a better solution. I was already creating simple single-file apps in HTML/JS/CSS and using localStorage as a DB. All I needed to do now was to make it possible to use those apps on my phone as well.
localStorage as an API
If you think about it, localStorage is very similar to a simple CRUD API.
localStorage.setItem() -> create and update localStorage.getItem() -> read localStorage.removeItem() -> delete localStorage.clear() -> delete all
If I could hook into those events and send the data to a server, I could basically implement data persistence for localStorage, without having to change anything in the code (except adding the script that will make the API calls of course). Unfortunately, localStorage is not triggering events for those actions. The next best solution was creating an object with the exact same API as localStorage, let's call it serverStorage and make it save the data to a server via API calls as well as saving to localStorage. Then I could simply run a search-and-replace on the files, to replace all instances of localStorage with serverStorage.
Waaait! Are you really going to send the whole data under a key to the server on each small change?
Nope, that was not acceptable. localStorage can hold up to 10MB of data, and I for sure don't want to send 10MB of data each time a checkbox is checked in the front-end.
That's when I discovered the glorious diff-match-patch library by Google. You give it two instances of (arbitrary) text, let's say A and B, and it will generate a patch, that you can apply to A to get B. Think of it as rsync for text. The patch is about as big in size as the change. All I had to do now was send the patch instead of the whole value of the key and then apply the patch on the server side.
Finally
Finally, I built a simple backend using the methods above to sync localStorage across devices. I had a github repo with all my apps, which I was pulling into a VPS. There I had a simple deploy script that was running the search-and-replace. I used nginx to create reverse proxy assigning each file a subdomain, because localStorage is scoped by host name. I pushed a file and the tool was instantly live.
Eventually, some friends wanted to try it too, so I turned it into a hosted tool called HTMLSync.io. It takes a single-file HTML and does the rest automatically. I might open source parts of it later if people are interested.
Discussions on HN
Admin
Author at HTMLSync. Passionate about creating tools and content to help developers build better applications.