Recently, personal projects have increasingly become a gold rush where people are focused on building the simplest "microsaas" possible in the hope of creating passive income. There's nothing wrong with profitable projects or launching a Minimum Viable Product (MVP) and iterating. In fact, that’s how most successful products are built, and its a practice I do myself. But in this article, I want to offer a different perspective: why you should deliberately complicate your personal projects as much as possible.
The Fun Factor
When I start a personal project, I usually have two goals: solve a problem I face in real life and improve my skills. This is why I often choose technologies I’m still learning or apply patterns I’m not fully comfortable with yet. It challenges me to deepen my understanding of these technologies, and since it’s a personal project, I have the freedom to make mistakes and learn from them. The freedom to try new things without constraints is what makes personal projects fun. The fun itself is the motivation that keeps the personal project from being abandoned like so many unfinished ideas that every engineer has.
In my professional life, I follow established patterns and maintain consistency within the codebase. In contrast, personal projects give me space to experiment. I try different approaches, play with patterns I’m unfamiliar with, and if I find them valuable, I start applying them in my professional work as well. This experimentation alongside the autonomy of making and learning from my own mistakes, makes the process more enjoyable.
Example 1: Custom Hearthstone Deck Validator
Take one of my recent personal projects, a custom Hearthstone deck validator. The project’s purpose was to allow users to define custom deck-building rules for tournaments or casual play. Instead of taking the easy route and creating dropdowns for predefined options, I complicated things on purpose. I opted for a text input where users could write the rules they wanted, which meant I had to create a Domain-Specific Language (DSL) to process and validate these rules.
To build the DSL, I revisited concepts I hadn’t touched since my compilers classes, such as tokenization. Rather than using regular expressions, I manually tokenized the input to have more control and flexibility. Manual tokenization allowed me to separate syntax and semantic validation, making error messages more helpful and detailed. This project was also the first time that using Test-Driven Development (TDD) genuinely enhanced my development experience.
On top of that, I learned about Monaco Editor (the same editor that powers Visual Studio Code) and decided to integrate it to provide real-time syntax highlighting for my DSL. I had to learn how to add a custom language to it, and it was incredibly satisfying when the editor correctly highlighted valid input and flagged errors. Each new piece of complexity taught me something new, things I would not have learned if I had taken the "easy" route.
Example 2: Hearthstone Set Review Hub
Another personal project that became more complex than necessary was the Hearthstone Set Review Hub. The core idea was simple: a central platform where players could rate new cards. That's something a basic spreadsheet could handle. But I decided to spice it up. I wanted to make it interactive for streamers by allowing their Twitch chat to submit ratings in real time directly to the hub.
This led me to learn about IRC protocol and discover tmi.js. The complexity escalated when I realized that I had to handle multiple streamers using the system at the same time, requiring creating and managing multiple instances of TMI clients.
Then, as the next Hearthstone expansion approached, I found myself on a tight deadline. I needed to release a working version before the expansion hype peaked (in approximately 20 days), which forced me to simplify my product. To make the most minimal viable product, I built a simple UI with just text fields and a button. Instead of using a database, I opted for Google Sheets to store the data, as streamers were already familiar with spreadsheets. My system would simply add a new page with chat ratings to their existing spreadsheet. I had to learn the Google Sheets API and handle its rate limits. To avoid exceeding the rate limit, I batched the ratings before writing them. But this introduced a new problem: how should the system handle multiple ratings for the same card? If a user sent more than one rating, how would I update the previous one if it was in a different batch?
I solved this by storing all ratings in memory until the streamer finished rating the card. Only then would I send the data to the spreadsheet. These decisions, even though they seem obvious in hindsight, were challenging under time pressure. Each problem I faced required a new skill or a new way of thinking. As my operating systems professor once said:
"My exams are easy. It’s simple to spot a deadlock or a race condition when you've spent the past months studying them and you're analyzing a piece of code that probably contains one. The real challenge is recognizing these issues when your production system is behaving unpredictably, and you're not even sure they could be the cause."
I released the project, and it was well-received by the community, leading to donations, contributor interest, and further development.
As development continued, I didn't stop challenging myself. This project significantly enhanced my skills in writing scripts to automate various tasks. It also deepened my understanding of observability, caching strategies, analytics, CI/CD, web scraping, and even Machine Learning. With the help of an old classmate, we trained a classification model to rate card after the expansion, using cards stats data to compare with the ratings users gave before the expansion.
Why Complicate Things?
Both of these projects became much more complex than they needed to be. But this complexity forced me to learn at an accelerated pace. The things I learned in just a few months compares to what I could have gained over years in a typical work environment. The key difference was that I was the one making the decisions, dealing with the consequences, and reaping the rewards when things went well.
At work, you typically have well-defined roles and responsibilities, and a lot of decisions are made by senior team members. You might specialize in one part of the stack, rarely touching others. But in a personal project, you're the architect, developer, tester, and product manager all in one. You control the technology choices, the design, and how deep you want to dive into different areas of the stack. This forces you to broaden your skills and become a more well-rounded developer.
Knowledge > Money
While these projects never had the goal of making money, the knowledge and experience I gained were far more valuable in the long run. They directly contributed to my career growth. I landed my current position because one of those projects caught the attention of a company. Additionally, these projects give me plenty to talk about in interviews and meetups. People get excited when I share the lessons learned, the decisions I made, and the struggles I faced.
Your career, like life, is a marathon, not a sprint. Focus on becoming valuable, and the rewards will follow, rather than fixating on getting money as quickly as possible.
So, my advice: complicate your personal projects. Choose technologies you’re unfamiliar with. Push yourself into areas you haven’t explored before. Learn from your mistakes. You’ll walk away with a wealth of knowledge, confidence, and skills that will benefit you far more than trying to build the simplest microsaas for quick cash.
Top comments (0)