Every few weeks, the same argument resurfaces: htmx is “the future,” React is “too heavy,” or vice versa. It’s loud, opinionated, and rarely useful. The real problem is simpler—and more practical: both camps often talk past each other because they’re not solving the same kinds of systems.

htmx and React aren’t rivals in the way people claim. They’re tools optimized for different architectural realities. Pick based on the shape of your application, where state lives, and how your team ships software—not based on who’s winning the comment thread.

What the Debate Gets Wrong: “Better” Isn’t a Category

“Which is better?” sounds productive until you notice it’s usually not asked in context. Better for what? Better for which constraints? Better for what team composition? Better for which latency model? Better for what maintenance pattern?

In practice, the decision is less like choosing a sports car and more like choosing a building material. Concrete and steel can both build bridges. But if you’re trying to assemble a temporary bridge quickly, you’ll likely make different tradeoffs than if you’re building something that must survive decades of load.

The htmx vs. React argument often fails because it treats the UI framework as the primary variable. In reality, the primary variable is the architecture: who owns state, how much logic runs on the server, and how complex interactions need to be.

When htmx Wins: Backend-Owned State and Server as the Source of Truth

htmx shines when the server is the natural home for your data and state. If your application already thinks in terms of requests, resources, permissions, and server-rendered views, htmx lets you keep that mental model while still delivering a modern “app-like” experience.

Concrete examples where htmx is a great fit

  • Admin panels and internal tools: You typically have CRUD flows, table views, filters, and form edits. The server already knows what the user is allowed to do. With htmx, you can progressively enhance without building a full client application.
  • Content sites with interactive widgets: Think comment forms, “load more” sections, search, voting, or admin moderation. Most interactions don’t need a fully client-managed state machine.
  • Workflows tied to backend invariants: If a state transition is enforced by business rules—like “you can’t approve until prerequisites are met”—keeping that logic server-side is not just convenient, it’s safer.

Why the architecture matters

htmx encourages you to treat HTML as the UI contract. You return markup that represents the new state, and you swap it into the page. When the backend is already the source of truth, this pattern reduces duplication. You avoid writing two versions of reality: one in the server and one in the browser.

And you avoid the “SPA tax” that hits teams hard: authentication edge cases, routing complexity, caching, rehydration, and state synchronization. You don’t need all of that if your system’s authority is the server.

When React Wins: Complex Client-Side State and Rich, Interactive UX

React excels when the browser must own meaningful local state and coordinate complex UI behavior that doesn’t map cleanly to round-trips.

Concrete examples where React is a great fit

  • Collaborative editors: Cursor positions, selections, operational transforms/CRDT updates, and frequent incremental changes benefit from client-managed state and optimized rendering paths.
  • Real-time dashboards: Live updates, streaming data, optimistic UI, and intricate layout logic are often easiest when the client maintains a local model of what’s on screen.
  • Complex component ecosystems: If your product needs deeply interactive UI primitives—drag-and-drop, advanced filtering, multi-step forms with intricate validation—React’s component model and local state management become compelling.

Why the architecture matters

When the interaction model is “the user is constantly changing something” and those changes need to feel immediate, a server round-trip isn’t just slower—it can be architecturally awkward. You want predictable UI state transitions, local derivations, and a rendering model that updates quickly.

React doesn’t just provide a view layer. It pushes you toward a design where the UI is a function of state, and that state can be complex and transient. That’s a good thing when the client is the natural engine of the interaction.

The Real Decision Framework: Where Does State Live?

Here’s the practical way to choose without tribal noise: identify where your application’s state lives and how often it changes.

Ask these questions:

  1. Is the backend the source of truth?
    If permissions, validation, and invariants are authoritative on the server, htmx aligns naturally.

  2. Do you need rich local state?
    If the UI depends on client-only details—like ephemeral UI state, optimistic changes, or interaction-heavy workflows—React is built for that.

  3. How “round-trip friendly” are your interactions?
    CRUD-heavy flows and form submissions are usually fine with request/response patterns. Fine-grained, continuous interaction tends to favor client state.

  4. What’s your team’s operating model?
    If your team is strongest in server development and wants to ship HTML-driven features quickly, htmx can reduce friction. If your team already lives in the client ecosystem and can maintain a component architecture, React can be a multiplier.

This is why the debate misses the point: it assumes the UI layer is the main event. The main event is the system boundary between server and client.

A Better Pattern: Combine Them Instead of Worshipping One

Here’s the opinionated take that should end most arguments: you can—and often should—use both. Many teams do.

A common hybrid approach looks like this:

  • Use htmx for server-rendered pages and incremental updates: pagination, filters, admin actions, form submissions, and small interactive fragments.
  • Use React for the parts that genuinely need client-owned complexity: a collaborative editor, a heavily interactive visualization, or a complex multi-step workflow.

This isn’t compromise; it’s correctness. You’re choosing the simplest tool that fits each problem. If your “hard part” is isolated, you don’t need to drag the whole product into a single architectural style.

Example: an admin tool with one React island

  • The admin panel is server-rendered. Tables, editing forms, and status changes use htmx swaps.
  • One section—say, an advanced configuration visualizer—uses React because it needs rich client-side state and a responsive UI.
  • The boundary stays clean: the React component can fetch data and send updates, while the rest of the system remains consistent with server truth.

This keeps your product coherent and your engineering effort focused where it matters.

Common Failure Modes (And How to Avoid Them)

Both sides have predictable ways to shoot themselves in the foot.

Failure mode for htmx

If you try to shoehorn a highly stateful, component-driven UI into htmx patterns, you’ll end up fighting the model. You’ll be forced to invent client-side state synchronization anyway—at which point you may as well ask whether React (or another client state system) would have been simpler.

Fix: Treat htmx as a server-centric enhancement tool. When local state complexity grows beyond “swap some markup,” isolate that complexity.

Failure mode for React

If you build a full SPA for an app where the server already owns the truth, you’ll spend time recreating things the server could have handled cleanly. The result can be a lot of glue code for routing, caching, permissions, and data consistency.

Fix: Don’t default to React when your problem is mostly CRUD, server-rendered pages, and backend-enforced invariants. Consider whether a request/response UI would reduce risk and speed up iteration.

Conclusion: Stop Debating Tools, Start Designing Systems

The htmx vs. React debate isn’t really about htmx or React. It’s about system design: where state lives, how interactions behave, and what your application must guarantee.

Pick the tool that matches your architecture, not the one that wins your timeline. If the backend is the source of truth and interactions are mostly request-friendly, htmx will make you faster and your UI more consistent. If the client must manage complex, transient state with highly responsive interactions, React will save you from contortions.

Make the boundary intentional, and the “war” goes away.