+++
title = "Why Gumroad Didn't Choose htmx"
date = 2024-09-30
updated = 2024-09-30
[taxonomies]
author = ["Sahil Lavingia"]
tag = ["posts"]
+++
At Gumroad, we recently embarked on a new project called [Helper](https://helper.ai). As the CEO, I was initially quite
optimistic about using [htmx](https://htmx.org) for this project, even though some team members were less enthusiastic.
My optimism stemmed from previous experiences with React, which often felt like overkill for our needs. I thought htmx
could be a good solution to keep our front-end super light.
Source with htmx - Click Image To View
In fact, I shared this sentiment with our team in Slack:
> "https://htmx.org/ may be a way of adding simple interactions to start"
And initially, it seemed promising! As one of our engineers at Gumroad eloquently put it:
> "HTMX is (officially) a meme to make fun of how overly complicated the JS landscape has gotten - much like tailwind is
> just a different syntax for inline CSS, HTMX is a different syntax for inline JS."
However, unlike Tailwind, which has found its place in our toolkit, htmx didn't scale for our purposes and didn't lead
to the best user experience for our customers–at least for our use case.
Here's why:
1. **Intuition and Developer Experience**: While it would have been possible to do the right thing in htmx, we found it
much more intuitive and fun to get everything working with Next.js. The development process felt natural with
Next.js, whereas with htmx, it often felt unnatural and forced. For example, when building complex forms with dynamic
validation and conditional fields, we found ourselves writing convoluted server-side logic to handle what would be
straightforward client-side operations in React.
2. **UX Limitations**: htmx ended up pushing our app towards a Rails/CRUD approach, which led to a really poor (or at
least, boring and generic) user experience by default. We found ourselves constantly fighting against this tendency,
which was counterproductive. For instance, implementing a drag-and-drop interface for our workflow builder proved to
be a significant challenge with htmx, requiring workarounds that felt clunky compared to the smooth experience we
could achieve with React libraries.
3. **AI and Tooling Support**: It's worth noting that AI tools are intimately familiar with Next.js and not so much with
htmx, due to the lack of open-source training data. This is similar to the issue Rails faces. While not a
dealbreaker, it did impact our development speed and the ease of finding solutions to problems. When we encountered
issues, the wealth of resources available for React/Next.js made troubleshooting much faster.
4. **Scalability Concerns**: As our project grew in complexity, we found htmx struggling to keep up with our needs. The
simplicity that initially attracted us began to feel limiting as we tried to implement more sophisticated
interactions and state management. For example, as we added features like real-time collaboration and complex data
visualization, managing state across multiple components became increasingly difficult with htmx's server-centric
approach.
5. **Community and Ecosystem**: The React/Next.js ecosystem is vast and mature, offering solutions to almost any problem
we encountered. With htmx, we often found ourselves reinventing the wheel or compromising on functionality. This
became particularly evident when we needed to integrate third-party services and libraries, which often had React
bindings but no htmx equivalents.
Source with NextJS - Click Image To View
Ultimately, we ended up moving to React/Next.js, which has been a really great fit for building the complex UX we've
been looking for. We're happy with this decision–for now. It's allowed us to move faster, create more engaging user
experiences, and leverage a wealth of existing tools and libraries.
Gumroad Helper Before & After - Click Image To View
This experience has reinforced a valuable lesson: while it's important to consider lightweight alternatives, it's
equally crucial to choose technologies that can grow with your project and support your long-term vision. For Helper,
React and Next.js have proven to be that choice.
Since we've moved there, we've been able to seriously upgrade our app's user experience for our core customers.
1. **Drag-and-Drop Functionality**: One of the key features of our workflow builder is the ability to reorder steps
through drag-and-drop. While it's possible to implement drag-and-drop with htmx, we found that the available
solutions felt clunky and required significant custom JavaScript. In contrast, React ecosystem offers libraries like
react-beautiful-dnd that provide smooth, accessible drag-and-drop with minimal setup.
2. **Complex State Management**: Each workflow step has its own set of configurations and conditional logic. As users
edit these, we need to update the UI in real-time to reflect changes and their implications on other steps. With
htmx, this would require numerous server roundtrips or complex client-side state management that goes against htmx's
server-centric philosophy. React's state management solutions (like useState or more advanced options like Redux)
made this much more straightforward.
3. **Dynamic Form Generation**: The configuration for each step type is different and can change based on user input.
Generating these dynamic forms and handling their state was more intuitive with React's component model. With htmx,
we found ourselves writing more complex server-side logic to generate and validate these forms.
4. **Real-time Collaboration**: While not visible in this screenshot, we implemented features allowing multiple users to
edit a workflow simultaneously. Implementing this with WebSockets and React was relatively straightforward, whereas
with htmx, it would have required more complex server-side logic and custom JavaScript to handle real-time updates.
5. **Performance Optimization**: As workflows grew larger and more complex, we needed fine-grained control over
rendering optimizations. React's virtual DOM and hooks like useMemo and useCallback allowed us to optimize
performance in ways that weren't as readily available or intuitive with htmx.
It's important to note that while these challenges aren't insurmountable with htmx, we found that addressing them often
led us away from htmx's strengths and towards solutions that felt more natural in a JavaScript-heavy environment. This
realization was a key factor in our decision to switch to React and Next.js.
We acknowledge that htmx may be a great fit for many projects, especially those with simpler interaction models or those
built on top of existing server-rendered applications. Our experience doesn't invalidate the benefits others have found
in htmx. The key is understanding your project's specific needs and choosing the tool that best aligns with those
requirements.
In our case, the complex, stateful nature of Helper's interface made React and Next.js a better fit. However, we
continue to appreciate htmx's approach and may consider it for future projects where its strengths align better with our
needs.
That said, we're always open to reevaluating our tech stack as our needs evolve and new technologies emerge. Who knows
what the future might bring?