Lists

Lists is a private (as in only meant to be used by me) multipurpose personal modular dashboard. At the moment, it contains two modules : a todo-list and a journal. It used to have a general note taking part but it’s been depreciated.

The functional stuff

Why I made it

I tried a lot of note taking apps (that I also used for todos) but I was never satisfied for many reasons. Most of them were too heavy like Evernote or Notion (I think Notion is great, has a lot of possibility, but it’s a pain to use when you only need a small subset of features) or lacked features like Simplenote (really fast but the editing wasn’t really what i wanted it to be). Some of these also had limits to their free tier and I didn’t want to have to face a decision in case i reached them. I thought I could do better, and I was partially right.

On building private apps

Making a productivity app that only i’m gonna use is a great experience as you can ignore a lot of stuff you need to take into account when making public apps. For example I don’t need to concern myself with registration/login, accessibility and UI/UX (only I need to be able to navigate and like it). I can also make it tailor made to my workflow.

The todos part

The basic example of app for most frameworks is a todo-list for a reason. They’re pretty easy to make, and it was no trouble making this one. Mine is just a basic list of entries that I can add, update and delete. The list is split in three based on how soon I need to adress the task : “sometimes”, “this week”, “today”. The first page has the “this week” and “today” list while a button allows you to switch to the “sometimes” list. Buttons allow me to move the entries around.

Basically it looks like this :

screenshot of the todos part

The journal part

This part was even easier to make, it’s just a text field that resets every day (at 5am). The data is stored in database but not accessible, as the idea was just to journal every day without reading past entries.

screenshot of the journal part

The notes part

Now this is where it gets interesting. My goal for this part was have an infinitely nestable bullet list, sort of how Workflowy works, as I really liked that idea at the time.

As it turns out, theres a lot of stuff you need to handle to have such a list.

I had a lot of issues with the database representation of a list like that, as each row was a database entry, and I needed a way to insert rows in the middle without updating the whole database. My solution was to store the previous row and update that. You also need to store the parent row (for nesting). This worked fine but there were other issues.

The second big one I faced was navigation and editing, as I wanted it to feel like one big textarea, but each row had to be a separate div (since it had a clickable bullet point for nested navigation). I also had to figure out how to handle delete (if you hit backspace at the beginning of a row, it merged with the one above, but the child rows had to merge too).

All these issues that i could only unsatisfiyingly solve made for a quite clunky app, and this is why I discarded it when I migrated the backend (more on that later). I now use Google keep for my notes, which i’m not completely satisfied with. I will probably rewrite this part in the future, using a more basic approach (individual tagged notes like keep, but with better markdown/rich text like editing, possibly using ProseMirror.

The tech stuff

The frontend

The frontend is written in Svelte. This choice was made mostly because it was “the new kid on the block”, and I had already tried Angular, React and Vue. It seemed promising and I liked the compiled approach (although I believe it leads to some hard to figure out errors). I’m very satisfied with it, it worked great, was easy to learn (thanks to a very good tutorial/documentation) and made me productive really fast. I really like the “html+js+css in one file” approach (also used by Vue) as it allows me to have it all in one place.

The database

CouchDB/PouchDB

This app was first made with PouchDB, backed up by CouchDB. The reason for this is that I originally wanted an offline first approach that synced to an online database. Using these two made that very simple, after the initial setup, you just write your data in pouchdb and it syncs automatically. I had an app that was updated everywhere in real time, and could function offline. The PouchDB api is very simple, the JS part is pretty small (I always aim for small apps) and it was perfect for the simple non relational data models I had (except the note part, but I don’t think another database would have helped). It really worked great overall for my case. I’m not sure how it would handle a multi-user approach but as I said I didn’t have to worry about that.

The reason I migrated was financial, the CouchDB database was hosted on a “free for 1 year” AWS EC2 instance, and when the year was up, I had to make a decision: either keep paying (something like 5€/month) or migrate to something in an “always free” offering.

One approach I could have took is migrating to IBM Cloudant (which is a hosted CouchDB compatible service), but I was afraid of the restrictions on the free tier (mostly the read/write stuff, as I didn’t control how much of that PouchDB was doing).

So I took another approach : AWS DynamoDB.

DynamoDB

DynamoDB is an AWS hosted NoSQL Database with a very generous free tier. Moving to it was honestly quite simple for the most part, I just had to plug the aws sdk, connect to it, change my objects a bit to remove PouchDB specific stuff (PouchDB was also NoSQL) and voila !

While the process was simple, I did end up losing quite a bit in the end, most notably the offline first/synced everywhere approach (now it just sends and request the data everytime in a “dumb” manner, and it doesn’t work offline) and the notes part.

Although I could have tried, I decided against porting the notes stuff as I wasn’t satisfied with it so the current version doesn’t have it (hence the lack of screenshots).

SQLite

The very first prototype version of this app actually used sql.js which is a WASM compiled browser version of SQLite. The idea was to work with an in memory sqlite database, and store the resulting sqlite file locally in IndexedDB, and remotely on AWS S3. Although i’m very fond of this idea in theory, in practice it was quite clunky to make it work as I wanted. I think there might be new tools that allow an easier version of this and I want to research that someday.