When I first started building HabitHeat, I did not really think of it as a long-term product.
It started more like a personal tool. Something I wanted for myself. I wanted to track habits, see them in a heatmap, and get a better feeling for what I was actually doing over time. The first version worked well enough for that. I used it myself, other people started using it too, and over time HabitHeat slowly became more than just a small side project.
But the problem was: the codebase never really grew up with the product.
HabitHeat v1 was built at a time when I was getting back into programming more seriously. I was also using Svelte for the first time. In the beginning, that was completely fine. The goal was not to build a perfectly structured product. The goal was to build something that worked. But because I kept adding features on top of that first version, the technical foundation slowly became harder and harder to work with.
At some point, I did not really want to open the code anymore.
That is usually a bad sign.
v1 worked, but it was built like an MVP
The first version of HabitHeat already had the core idea. It had heatmaps. It had year, month, and week views. It had mini stats inside the habit cards. It had customization, including different colors and intensity levels for number habits, similar to how GitHub contribution graphs get darker when the value is higher. It also had journal entries, so a habit entry could be more than just a number or a checkmark.
So the idea was there.
But the implementation was not where it needed to be.
A lot of the app was still built like an MVP. I had too much logic directly inside page files. Many things were not properly split into reusable components. The database structure was not flexible enough for the kind of habit tracker I wanted HabitHeat to become. It worked for the current version, but every time I wanted to add something new, it became harder than it should have been.
One example was the options habit type. I added it to v1, but it was already painful to implement. It worked, but it showed me how limited the foundation was. I also wanted to add a timer habit type, but after building the options type, I knew that adding another habit type on top of that structure would be even more exhausting.
That was one of the clearest signs that the app needed a rebuild.
I did not just need to add more features. I needed a better foundation.
The product direction had changed
Another reason for the rebuild was that HabitHeat had changed as a product.
The first version was still connected to ideas like streaks, achievements, points, and more gamified habit tracking. I had thought about those things a lot, and at some point I even added Stripe and subscriptions for premium features like more habits. A few people actually paid for it, which was cool to see, but looking back, it did not really feel right.
The app was not good enough yet to justify that kind of monetization. At least I would not have paid for it myself in that state. So eventually I removed it again.
That also changed how I thought about HabitHeat. I did not want it to become a habit app that locks the most important parts behind a paywall. And I also did not want it to be built around streak pressure, gamification, or artificial motivation. The more I used HabitHeat myself, the more I cared about something else: heatmaps, history, analytics, and understanding habits over time.
But v1 had not really been built with analytics in mind.
I added some analytics near the end of v1, but it felt more like something I forced into the existing structure. It was not clean. It was not optimized. It was not based on a data model that made deeper insights easy. The UI was not great either. It worked in the most basic sense, but it was not the experience I wanted.
HabitHeat v2 became the chance to rebuild the product around the direction it was actually moving in.
Less gamification.
More history.
Better data.
Better analytics.
A calmer and more useful experience.
The user experience was not good enough
HabitHeat v1 was usable, but it was not polished.
The UI was rough. The UX was not great. Loading states were not good. Performance was not where I wanted it to be. Mobile was not as nice as it should have been. Analytics were not really part of the product in a clean way. And overall, the app still felt like something that had grown from a personal experiment into a public product without ever getting the rebuild it deserved.
That is not unusual for side projects. It is actually pretty normal.
You start with an idea. You build quickly. You test. You add things. Then real users appear, and suddenly the project has to support things you did not plan for in the beginning.
That is basically what happened with HabitHeat.
The app had users. People were creating habits and logging entries. I was still using it myself. But every time I wanted to improve it, the old foundation slowed me down. There were long pauses where I barely worked on HabitHeat, not because I did not care about it, but because working inside that codebase was not fun anymore.
And that bothered me, because I still used the app.
I had not lost interest in the product. I had lost interest in the old version of the product.
That difference was important.
Why I could not just improve v1
In theory, I could have improved v1 step by step.
I could have refactored one component at a time, slowly changed the database structure, migrated parts of the UI, and kept the old version alive while improving it. But in practice, that did not really make sense.
The problems were too deep.
The code structure was not good. The database structure was not good enough for future habit types. Analytics needed a better foundation. The UI needed a more complete redesign. I wanted the app to support multiple entries per day for number habits. I wanted to store better time information. I wanted a proper timer habit type. I wanted a cleaner component system. I wanted better performance, better loading states, better mobile behavior, dark and light mode, and a product structure that would not fight me every time I wanted to build something new.
At that point, a rebuild was faster than trying to save the old version.
And that is exactly what happened.
Once I started rebuilding HabitHeat from scratch, it actually went surprisingly fast to reach the old feature level again. That is one of the nice things about rebuilding a product you already understand. The first time, you are figuring out what the product even is. The second time, you already know what needs to exist. You can build it much more intentionally.
v1 was the exploration.
v2 was the foundation.
What changed in v2
HabitHeat v2 is still the same product at its core.
It still has heatmaps. It still has year, month, and week views. It still has habit cards, colors, customization, journal entries, and stats. It still helps you track habits and see them over time.
But almost everything underneath is cleaner.
The new data model makes it much easier to support different habit types. The code is component-based instead of having too much functionality directly in page files. The analytics logic is cleaner. The UI is more polished. The app is easier for me to maintain and extend.
One of the biggest changes is how entries work.
In v1, a habit was much more limited. For number habits, you could basically only have one value per day. But that is not how real habits always work. I might meditate two or three times in a day. Someone else might study in multiple sessions, work out twice, or track several walks. In v2, multiple entries per day can be tracked properly and then added up for that day.
That sounds like a small detail, but it changes the whole product. It makes HabitHeat more honest and more flexible.
v2 also added a timer habit type. You can start and stop a session and track time-based habits like study sessions, focus time, walking, exercise, or deep work. This was something I wanted for a long time, but v1 was not built in a way where adding it felt good.
The whole app experience is also much better now. There are toasts when something happens, loading spinners, skeleton states, subtle fade-in animations, better performance, cleaner cards, a better sidebar, and a much more polished interface overall. Dark and light mode were also added, which many users wanted.
It is still not perfect, but v2 finally feels like a real product.
Analytics became much more important
One of the biggest product changes in v2 is analytics.
In v1, analytics were more of an afterthought. I added them late, and they were not built on a strong foundation. In v2, analytics are much more central to how I think about HabitHeat.
A heatmap is great for seeing the habit visually. But analytics help you understand what changed.
How many minutes did you meditate this year? Which months were strongest? Which weekdays worked best? How did this year compare to last year? How much did your total volume change? Are you consistent, or do you mostly show up in short phases?
That is the kind of thing I personally love about HabitHeat.
For example, my own meditation habit is not just a set of purple squares. It has years of data behind it. I can see that 2024 was stronger than 2025. I can see average session length. I can see total minutes. I can look at gaps and remember what was happening in my life at that time.
That is where HabitHeat becomes more than a checklist.
And v2 is the version where that direction finally started to make sense technically and visually.
Why I did not migrate the data automatically
One difficult decision was migration.
Because the database structure changed so much from v1 to v2, an automatic migration would have been complicated. In theory, I could have built one. But I did not want to risk breaking or incorrectly moving user data.
Habit data is personal. Even if it looks simple from the outside, it can represent months or years of someone’s life. I did not want to run a migration that might accidentally change something important.
So I decided to keep v1 online and accessible instead.
HabitHeat v1 is still available as a read-only version with all old habit data. Users can open it, view their old habits, and manually move anything they want to keep into v2. That is not the most convenient solution, but it felt safer and more honest than forcing a risky migration.
I had to move my own data manually too.
That was annoying, but it also reminded me why the rebuild mattered. If people are going to build long-term habit history in HabitHeat, the foundation needs to be strong. The app has to be something I can keep improving without constantly fighting the structure underneath it.
The rebuild was worth it
Looking back, rebuilding HabitHeat from scratch was absolutely the right decision.
I do not regret it.
The old version had reached its limit. It proved that the idea was useful, but it was not the version I wanted to keep building on for years. v2 made HabitHeat feel alive again. It gave me a codebase I actually wanted to work in. It gave the product a cleaner foundation. And it made future features much easier to imagine.
Since v2, HabitHeat has also started growing more consistently. I get new registrations almost every day now. There has not been a day without a registration in a long time. That still feels kind of crazy to me, because for a long time this was just something I built for myself.
The app also gets more feedback now, partly because I ask for it more clearly inside the product. That feedback helps a lot. It shows me where people get confused, what they want next, and which parts of the app actually matter to them.
That is probably one of the most motivating parts of building HabitHeat right now.
It is no longer just me using the app.
Other people are building their own habit histories in it too.
What I learned
The biggest lesson from rebuilding HabitHeat is that a rebuild can be dangerous, but sometimes it is the right move.
Rebuilding can become an excuse to avoid hard product work. It can turn into a loop where you keep starting over instead of improving what already exists. I know that risk. But in this case, the rebuild was not about chasing a new stack or making things perfect for no reason.
It was about removing the friction that stopped me from building the product properly.
v1 was valuable because it helped me understand what HabitHeat should be. It showed me what mattered, what did not matter, which features I actually cared about, and where the technical foundation was too weak.
v2 took those lessons and turned them into a better product.
If there is ever a v3, it might not be another full redesign or rebuild of the interface. It might be more about the backend and infrastructure. Maybe one day HabitHeat should move away from relying so heavily on a backend-as-a-service and use a more custom backend and database setup. I am not sure yet. For now, the current foundation works well, and I do not want to rebuild just for the sake of rebuilding.
But I do want HabitHeat to keep getting stronger.
What v2 made possible
The best thing about v2 is that it gives HabitHeat room to grow.
More habit types are easier to add now. Analytics can become deeper and more useful. Public profiles and read-only habit embeds are possible. Data export, better templates, a native app, better onboarding, yearly recaps, and more advanced integrations all feel much more realistic now than they did in v1.
That is the real value of the rebuild.
It was not just about making the current app look better. It was about making future HabitHeat possible.
v1 was the first real version of the idea.
v2 is the version I can actually build on.
And that is why I rebuilt HabitHeat from scratch.
— Philip






