5 min read
Launch Your Ugly Code
Live products: kepplifinance.com · capturioo.com
I’ve read Joel Spolsky’s essay about Netscape. I know the usual advice: don’t throw away working software, refactor incrementally, delete old code. I knew all of this before I opened my editor and typed the first line of Keppli Finance.
I shipped ugly code anyway.
How It Started
Keppli Finance began as an experiment. A personal finance app for Latin America, built in my spare time to learn and improve. No formal roadmap. No launch date. Just a place to explore ideas.
The problem with experiments is that, if the idea is good, they stop being experiments.
At some point the app started making sense. The features fit together. The product was real. I decided to launch it.
That’s when I opened the source code and felt uneasy.
Business logic mixed with presentation logic. Functions that did three different things. Variable names only I understood at 2 a.m. when I wrote them. It wasn’t a complete disaster — it worked — but every new feature was surgery without a medical history.
The Usual Advice (and Why I Ignored It)
The obvious answer was to rewrite. Start with a clean architecture, good conventions, test coverage from day one.
But every article about rewrites is written from a team’s perspective. Companies with engineers, budgets and stakeholders. They assume you can maintain two systems in parallel during migration.
I was just me. Working on this between client projects, in time gaps that sometimes lasted four hours and sometimes four days.
The situation is different when it’s just you.
So I did what any sensible developer in my position would do: I shipped it.
The First Days
The launch was quiet. I shared the link and waited.
The first 10 users arrived. Then 50. Then 100.
And with every user came things no test covers: flows I considered obvious that nobody else understood, bugs in edge cases I never imagined, support questions that revealed gaps in the product that perfect code would never have detected.
The code was ugly. The product was real. And that changed everything.
Because suddenly I had something I didn’t have before: feedback from real users doing real things.
The Part Nobody Writes About
Every article about clean code and refactoring talks about technical debt in terms of performance, scalability, maintainability. Those are real concepts, but there’s another risk nobody mentions when you’re an independent developer working on a side project:
Motivation.
I’ve abandoned projects before. Not because the idea was bad or the code was broken, but because the distance between where I was and where I wanted to be felt infinite, and I lacked the energy to cross it. Rewriting doubles that distance. You don’t move forward; you reconstruct already-covered ground, just cleaner.
Rewrites don’t fail because the new code is worse. They fail because they never get finished.
Shipping with ugly code wasn’t a technical decision. It was a project survival decision.
How I Improved the Code (With Users Pushing Me)
What I did instead was more boring and more effective: incremental improvements, guided by the real pressure of real users.
Three simple rules:
- Any new feature gets written to the standards I want to have.
- When I touch old code for a fix or feature, I leave it better than I found it.
- When something hurts so much that it blocks development, that’s when I refactor it with full focus.
Not glamorous. But it worked.
With Keppli, the code from the first months looks nothing like what it is today. There was no total rewrite moment — there were hundreds of small moments where every time I opened a file, it came out a little better.
When I launched Capturioo, my second app, I was already making fewer design mistakes from day one. Not because I had studied software architecture, but because I had suffered the consequences of not doing so.
What Happened
Today, Keppli Finance has more than 1,000 active users. Capturioo, which is much newer, already surpasses 40 users and grows week over week.
Those numbers weren’t generated by clean code. They were generated by shipping.
And the code that exists today — imperfect, improvable, with parts that still embarrass me — is infinitely better than the perfect code I would have written if I’d stayed refactoring before launch. Because that perfect code would have no users. It wouldn’t have survived long enough to improve.
What makes code get better isn’t having time to refactor. It’s having users who force you to.
What I Really Learned
The biggest risk for an independent developer isn’t bad architecture. It’s never reaching the market.
Every developer has the instinct to rewrite. We read messy code and the first thing we think is: “Let’s start over”. That instinct grows stronger when you have the tools to do it right. Modern frameworks, linters, test runners, AI agents that help you generate pristine code. They make a clean rewrite feel very feasible.
And technically, it is. But “technically feasible” and “actually going to get finished” are two different things.
Refactor what you already have. Ship it. Test it with real users. Let the architecture evolve under the pressure of real people doing real things. The code won’t be perfect. It doesn’t have to be.
It just has to exist.
Launch your ugly code.