Picking up from the chaos
In Part 2, I shared the horror story: 5,000 lines of spaghetti code in a single file. HTML mixed with JavaScript, global onclick handlers, and enough setTimeouts to make any senior engineer cry.
It was clear that if I wanted Sortit.Now to survive, I needed to impose some order. Not the perfect architecture I'd enforce at work, but something that would let me keep moving without constantly breaking everything.
This is the story of how I went from "I don't even want to open this file" to "okay, this is ugly but manageable."

Why architecture matters, even in a side project
At first, I thought I could ignore architecture. It's just a side project, right? Who cares if the code is a mess, as long as it works?
But then reality hit me: without some structure, every new feature had a hidden cost. Add one thing, break two. Change a detail, lose a whole module. The AI was fast, but without guardrails, it was building a house of cards.
And the truth is, this is not new. That's exactly what happens at every company that implements software. It's the reason why clean code, testing, and best practices are mandatory in our sector. The only difference was that with AI, I felt like maybe I could skip all of that. It felt like speed made structure unnecessary. I was wrong. AI needs those practices in the same way normal developers and production-ready software need them.
The goals for the refactor
I wrote myself a simple list:
- Split the monster file. No more 5,000 lines of doom.
- Separate responsibilities. Views here, services there, state in one place.
- Make features independent. Adding a "people" feature shouldn't break tasks and actions.
- Give AI rules. A basic architecture contract it could follow.
- Keep it simple. This wasn't about showing off clean code, it was about survival.
The first steps
I started small.
- I created new folders for every module.
- I created a views/ folder inside each module and moved UI components and HTML files there.
- I created a services/ folder inside each module for things like projectsService, tasksService, peopleService.
- I created an assets/ folder inside each module for the styles and moved all global styles to another folder.
- I asked the AI to write a very basic dynamic view loader so every new screen didn't reinvent the wheel.
It wasn't beautiful. Honestly, it was barely acceptable. But it immediately made my life easier. I could tell AI "only touch views/People.jsx and services/peopleService.js" and it usually behaved. It also helped me prevent the AI from breaking things at every change, since there was finally a clear logic separation.
Teaching AI the rules
I learned quickly that AI doesn't remember rules unless you keep repeating them. So I wrote a one-page architecture contract that I copied into almost every prompt:
- Views go in views/
- Services go in services/
- Assets go in assets/ or global styles
- Use the dynamic view loader, don't create new hacks
- Don't use setTimeout for async fixes
It felt silly at first, like explaining basic stuff to a junior developer. But it worked. AI became more predictable, and I spent less time cleaning up messes.
Living with "good enough"
Would I let any of my engineers at work ship this architecture? No way. It was too basic, too fragile, and full of compromises.
But here's the thing: for this project, "good enough" was perfect. It gave me back my speed without constant breakdowns. It turned AI from a chaos machine into a somewhat reliable partner.
And, most importantly, it made me want to keep building.
The features that survived the refactor
After cleaning things up, I could finally add features again without panicking. Some highlights:
- Tasks and actions felt solid. I could add, edit, and view them without weird side effects.
- The people module became easier to extend, like adding details or linking people to projects.
- Google integration worked consistently, without random timeouts or crashes.
- The UI started to feel like an actual product, not just a proof of concept.
Every win made me more confident that the project had a future.
The emotional shift
The biggest change wasn't technical, it was emotional.
- Before: every new feature was exciting but also scary, because I never knew what would break.
- After: I still had frustrations, but I felt like I was in control. The app was no longer a wild horse dragging me around. I was holding the reins.
It wasn't glamorous, but it was sustainable.
Lessons learned
- You don't need perfect architecture, but you need some. Even the simplest structure pays off.
- AI needs rules. If you don't tell it where to put things, it'll put them anywhere.
- Good enough is better than nothing. Don't aim for the cleanest code, aim for survivable code.
- Refactor early, but not too early. I waited too long, and it cost me weeks.
- Clean code isn't optional. AI doesn't change the fundamentals, it just tricks you into thinking you can skip them.
- Emotion matters. If your codebase makes you dread opening it, you won't keep building.
Closing
This refactor wasn't glamorous. It wasn't elegant. But it was the turning point that let me keep building Sortit.Now. Without it, the project would have collapsed under its own chaos.
In Part 4, I'll share how the UI and UX evolved, how I went from a functional but ugly interface to something polished enough that I could actually imagine releasing to the world. Spoiler: it involved more AI magic, more frustration, and me realizing I care about design way more than I thought.