DEV Community

Cover image for What Led Me to Creating OpenHabitTracker and Lessons Learned
Urban
Urban

Posted on

What Led Me to Creating OpenHabitTracker and Lessons Learned

OpenHabitTracker is a free, ad-free, open-source habit tracker app that works on Windows, Linux, Android, iOS, macOS, and as a web app. You can find the source code on GitHub.

The Journey to Creating OpenHabitTracker

I used Google Keep for a long time, but the more I used it, the harder it became to organize my notes. I tried using labels a few times, but without much success.

Then, I began using OneNote to keep track of tasks that weren’t done daily (like cleaning the windows in all rooms or taking the car to the car wash). In the note, I listed a dozen tasks along with the dates they were last completed, but soon I found myself wishing for a tool that could better manage this.

Google Calendar is good for repeating tasks, but finding out when you last completed a particular task can be bothersome—you have to search through previous weeks or months. Most habit tracker apps are great for tracking streaks, but if you miss a task, they fall short. You know you didn’t do it, but you don’t know when you last did it, how much time has passed since, or what the average repeat interval is compared to your desired repeat interval.

This is why I decided to create my own app.

My Programming Background

I wrote my first program in September 1989, during primary school, using QBasic, and I've been programming ever since. For the first 15 years of my programming career, I worked with game engines—writing my own for my university thesis, working on an in-house engine at one company, and using Unity at another. I had almost no experience with UI, UX, HTML, CSS, JS, SQL, or any other web technologies or databases.

First Attempt: Daily Checklist and Tracker

On July 24, 2016, I started working on Daily Checklist and Tracker using PHP and MySQL. I managed to create a simple website with a task list and three types of tasks:

  • Tasks to be done ASAP, with measured duration
  • Tasks to be done once on a specified date, saving the time when they were finished
  • Tasks with a repeat interval

It had all the features I missed in Google Keep, but nothing else. The design was awful—or rather, there was no design at all, not even "programmer's art"—making it unusable.

Lesson learned: User interface and user experience are as important as the features. You have to learn some design.

Second Attempt: Priority Task List

On December 24, 2017, I started working on Priority Task List using Vue.js, CouchDB, and PouchDB. I consider it a vast improvement over my first attempt. It had a menu, help section, and allowed you to group tasks into categories. Each task displayed the time elapsed since it was last completed and the number of times it was completed. It also had an automatically computed priority that changed with time and a priority factor that determined how quickly the priority increased.

This time, I paid more attention to UI, but I had no experience with responsive design. The website had a mobile-first design—perhaps mobile-only design—with just one layout for all screen sizes. It had every feature I wanted, presented on screen the way I wanted, but the user experience was still lacking. You can still try it out here.

Lesson learned: Even if you learn some design and create the UI the way you want, it might not create a good user experience.

Third Attempt: What Should I Be Doing Right Now

On September 16, 2018, I started working on What Should I Be Doing Right Now using Vue.js, CouchDB, and PouchDB. I had an exciting new idea: users could write JavaScript code to determine which task should be done next, based on which tasks were marked as done on a list. The website would take the JavaScript as a string and execute it in code, allowing users to determine what they should do next based on their own rules and a list of tasks with checkboxes.

It was a fun experiment, but not very useful in day-to-day life. You can still try it out here.

Lesson learned: Sometimes, you have to test your ideas, even if they don’t prove to be the best.

Fourth Attempt: What Should I Be Doing

On May 12, 2019, I started working on What Should I Be Doing using PHP and the Google Reminders API. I had another exciting idea: using the existing Google Reminders API to work with Google Reminders and add missing features to a website. Since I couldn’t find a PHP wrapper for the Google Reminders API, I decided to write one myself (Google Reminders PHP) and also created one for JavaScript (Google Reminders JS).

However, this took most of my time, and the website itself didn’t progress. I didn’t add any features beyond listing the reminders you have in Google Calendar and Google Keep.

Lesson learned: Don’t start projects where you’ll spend more time writing missing libraries than working on the project itself.

Fifth Attempt: The Last Time

I became interested in Microsoft Blazor with the release of .NET Core 3.0 and started learning it. On October 4, 2020, I began working on TheLastTime using Blazor with .NET Core 3.1. With the release of .NET 5 on November 10, 2020, I upgraded the project to .NET 5. This was my first Blazor app, and I thoroughly enjoyed working on it—using C# on the client side gave me IntelliSense in Visual Studio, which wasn't available with JavaScript.

The app had a good design, a friendly UI, and was a pleasure to use—this was the first time I found myself daily using a program I had created. Using the app helped me significantly reduce procrastination and develop a few habits that I had struggled with before. The app worked on the web with Blazor WASM and on Windows with WinForms and WPF, where I used WebView to host Blazor. Most of the Blazor code was shared between all three projects.

The app included all the features of my Priority Task List project, such as habit tracking and task grouping by categories. Additionally, it introduced new features: custom categories, advanced Search, Filter, and Sort options for customizing your view, and 26 Bootswatch themes for Bootstrap. The app also supported user data export/import in JSON and YAML formats and allowed users to back up JSON to Google Drive.

However, the NuGet library I used for IndexedDB reloaded everything on every change. At first, this wasn’t an issue, but after a year, the app became so slow that it was unusable. It was clear that I needed a better library for IndexedDB, but since it was so deeply integrated into my code, I realized that a complete rewrite would be faster. You can try it out here.

Lessons learned:

  1. When using third-party libraries, it pays off to get to know them better, especially if they are not widely used or are developed by a single person.
  2. Using abstractions and interfaces is considered best practice in C# for a reason—don’t ignore them.

Sixth Attempt: Ididit!

On April 15, 2022, I started working on Ididit using Blazor with .NET 6. With the release of .NET 7 on November 8, 2022, I upgraded the project to .NET 7. I aimed to make the app truly cross-platform, so in addition to WASM, WinForms, and WPF, I also explored Microsoft MAUI, Chromely, Electron.NET, and Photino.

Using Blazor with Chromely and Electron.NET proved to be difficult and slow, and both libraries were too bloated for my needs. Photino allowed me to create a Linux version of the app. With MAUI, I could develop Android and iOS versions and publish them to the Google and Apple stores. I also published the MAUI version to the Microsoft Store and didn't bother with WinForms and WPF versions.

I decided to implement all the features from TheLastTime and more, all at once. However, this approach caused the design to suffer—the UI wasn’t polished, and the app became bloated with features. The app combined notes, tasks, and habits into one bloated list. I added nested categories and a category tree, which proved to be unnecessary as I never used the feature myself.

The app also had a few good improvements:

  • Markdown support for notes
  • User data export/import in TSV and Markdown in addition to JSON and YAML
  • Import Google Keep notes by uploading the ZIP file produced by Google Takeout
  • Localization to English, German, Spanish, Slovenian, and Czech

Because I wanted to write as little platform-specific code as possible, I thought using IndexedDB on desktop through WebView was a good idea. However, it didn’t work as well as using the platform's native file access. I also programmed file open/save for user data export/import with JavaScript on all platforms, and while it worked on web and desktop, it didn’t perform well on mobile. Although I used abstractions and interfaces this time, I didn’t structure the code independently enough. You can try it out here.

Lessons learned:

  1. If you’re rewriting a project from scratch, don’t add all the features and ideas you had before at once—first rewrite the proven features, then start adding new ones.
  2. Sometimes, it’s better to write platform-specific code rather than force a platform-independent solution, even if it’s possible.
  3. Writing interfaces for their own sake is as bad as not writing them—if you suspect you might need a different implementation, plan for it when writing the interface.

Seventh Attempt: OpenHabitTracker

On November 14, 2023, I started working on OpenHabitTracker using Blazor and .NET 8, which was released on that day. This time, I decided to take all the good parts of my first Blazor app, TheLastTime, and combine them with the good aspects of Ididit while fixing its problems:

  • The app has a good design and polished UI.
  • IndexedDB is used only for WASM, while SQLite with EF Core is used for desktop and mobile.
  • User data export/import is done with native file open/save dialogs on each platform.

I also introduced new improvements:

  • All HTML, CSS, and JS files are now embedded, so the app doesn’t depend on an internet connection.
  • Categories have been simplified—they are no longer nested, so there’s no need for a tree.
  • Notes, tasks, and habits are now in separate lists, which can also be sorted by priority.
  • Search, Filter, and Sort features have been improved.
  • Added a Trash feature so deleted items can now be recovered.
  • All 26 themes now also work in dark mode.

Top comments (0)