What Shipping Products Taught Me About Building Apps
Why real-world complexity is the best teacher for any software engineer or product builder.
We spend a lot of time in the developer world talking about the "ideal" way to build things. We read about the perfect architecture, the most elegant state management patterns, and the latest and greatest frameworks. But the moment you move from a side project to a real product with real users, those ideals often clash with reality.
Shipping Merch Factory and other platforms has taught me that the real world is messy, unpredictable, and much more demanding than any tutorial suggests. Here are the core lessons I've learned from the trenches of shipping.
1. Shipping is a Feature
In my early days, I would delay releases for weeks, trying to get every line of code perfect. I believed that the "quality" of the code was the most important metric. I was wrong. The most important metric is Impact, and you can't have impact if the code is only running on your local machine.
The "Next-Gen" way to build is to prioritize shipping. A feature that is in the hands of users—even if it's slightly unpolished—is 100x more valuable than a "perfect" feature that is still in development. This doesn't mean you should ship broken code; it means you should ship the Minimum Viable Value.
Check out my thoughts on why the next-gen web needs better products, not more code.
2. Technical Debt is a Business Decision
We often talk about technical debt as a failure of engineering. But in reality, it is often a strategic business decision. When we were building the initial store integrations for Merch Factory, we had to choose between a perfectly clean, abstracted multi-store connector or a hard-coded solution that worked for our first ten customers.
We chose the hard-coded solution. It allowed us to launch in two weeks instead of two months. Yes, we had to refactor it later (a process I describe in my technical deep dive on the system architecture), but those two months of real-world feedback were invaluable.
Technical debt is fine, as long as it's Intentional Debt. The key is to have a plan for paying it back once you've validated the product value. This is how you build for the next-generation web.
3. The "Ideal" Stack is the One You Know
It is tempting to start every new project with the latest shiny framework. "I'll use Next.js with the newest experimental features!" or "I'll try this new CSS-in-JS library!" While this is great for learning, it's often a disaster for shipping.
When we migrated Merch Factory to MUI v7, we did it because it solved a specific problem with our data-heavy dashboards, not because it was the newest thing. We stuck with what we knew (Next.js and Firebase) because that familiarity allowed us to iterate with incredible speed.
If your goal is to ship, choose the tools that allow you to move from idea to production-ready fast. For me, that’s almost always Next.js, Tailwind CSS, and MUI.
4. Complexity is a Lifecycle
Every product starts simple. As you add users and features, complexity is inevitable. The job of a builder isn't to avoid complexity, but to manage and hide it from the user.
A great example of this is the Merch Factory design customizer. The interface is simple: you upload an image and position it. But the underlying system—using Konva.js for canvas manipulation and complex image processing—is incredibly complicated.
Complexity should live in the Backend, not the User Experience. If a user has to "learn" how to use your product, you've failed to hide the complexity well enough. Read more about how I use Konva.js to solve visual complexity.
5. Listen to the Friction, Not Just the Feedback
Users are great at telling you what they think they want. But they are even better at showing you where they are struggling. When we noticed that creators were spending too much time manual syncing their stores, we didn't just add a "Sync All" button. We went deeper.
We used the Wix SDK to provide deep, bi-directional syncing. We removed the friction entirely. Don't just build what users ask for; build what removes the friction from their workflow. This is how you build a product that people actually rely on. This is a core part of our e-commerce architecture strategy.
6. Build for the "Unhappy Path"
In a tutorial, everything goes right. In production, everything can go wrong.
- The Razorpay payment might fail.
- The Firebase function might time out.
- The Wix API might return a 500 error.
Shipping taught me to build for the "Unhappy Path." Every external integration, every asynchronous operation, and every user input needs a failure strategy. If you don't build it now, you'll be building it at 3 AM when the site goes down. This is the difference between a prototype and an enterprise-grade app like Merch Factory.
7. The Power of Personal Branding
Finally, I’ve learned that shipping is only half the battle. The other half is telling the story. This is why I built this portfolio. A portfolio shouldn't just be a list of links; it should be a demonstration of your ability to ship.
By sharing my process—from starting a clothing brand in India to the logistics of POD—I’m not just showing code; I’m showing Operational Depth. It’s proof that I can handle the full product lifecycle.
Final Thoughts: The Mindset of a Builder
Shipping isn't a one-time event; it's a discipline. It's the daily practice of making trade-offs, managing complexity, and focusing on user impact over technical perfection. It's about being intentional with your code and ruthless with your execution.
If you're a developer who wants to become a builder, my best advice is simple: Start shipping. It will be messy, and you'll make mistakes, but those real-world lessons are more valuable than any perfect abstraction you'll ever write.
You can see the results of this discipline at merchfactory.in.