Welcome to Module 7. In the previous modules, we've systematically built up your new toolkit: we established the hypermedia-driven architecture, set up a server with Express, mastered HTMX's core mechanics, and finally, augmented our applications with client-side state using Alpine.js and vanilla JavaScript. You now possess all the individual tools needed for your migration.
This lesson marks the beginning of the central part of this course: creating The React-to-HTMX Migration Playbook. Our objective is to synthesize everything you've learned into a formal process for analyzing your existing React applications. Specifically, we will establish a decision rubric for classifying React components into one of three migration targets: a server-rendered page, an HTMX-driven partial, or a client-only component.
This rubric will be the cornerstone of your migration strategy, allowing you to approach the process not as a chaotic rewrite, but as a series of deliberate, well-reasoned architectural decisions.
The Core Architectural Choice: Where Does State Live?
Before we can classify components, we must revisit the fundamental philosophical divide between React and HTMX. As an experienced React developer, you are accustomed to the client-side application model: the server provides JSON, and the React app is a stateful runtime in the browser responsible for rendering, routing, and managing complex state trees.
HTMX deliberately inverts this. It pushes the responsibility for generating UI and managing application state back to the server. The video "HTMX, the anti JS framework" provides a concise explanation of this shift.
HTMX, the anti JS framework (vs React)
This clip from Kodaps Academy clarifies the core philosophy of HTMX regarding application state.
Watch the segment from this point where the narrator explains how HTMX places the responsibility for updating the display state onto the backend. Then, continue through the next part, which clarifies that this philosophy applies to "meaningful" application state, not transient UI state like a dropdown being open here.
This distinction is the first principle of our rubric. When you look at a React component, the first question to ask is: "What kind of state is this component managing?" Is it "meaningful" state that belongs on the server, or transient UI state that can live on the client?
The Three Migration Targets
Based on this principle, every component in your React application can be mapped to one of three targets in your new architecture:
-
Server-Rendered Page: This is a full HTML document rendered by an Express route. It's the destination for what used to be a distinct page managed by React Router. It serves as the container for other, more dynamic elements.
-
HTMX-Driven Partial: This is a fragment of HTML, rendered by a dedicated Express endpoint, and swapped into the page by HTMX. This is the primary target for any React component that was responsible for its own data fetching, submission, or updates (e.g., sortable tables, search result lists, forms).
-
Client-Only Component: This is an interactive element whose logic and state are handled entirely in the browser, without a server roundtrip. This is the target for UI widgets like modals, tabs, and dropdowns, and will be implemented using Alpine.js or, for simpler cases, vanilla JavaScript via
hx-on.
Building the Decision Rubric
To systematically classify your components, we will construct a rubric based on a series of diagnostic questions. The article "htmx in 2026: When You Don't Need React" provides an excellent high-level framework for this.
htmx in 2026: When You Don't Need React (And ... - DEV Community
This article provides a clear breakdown of the strengths and weaknesses of each architectural style, which directly informs our rubric.
Please read the following three sections: Start with The Core Architectural Divide to reinforce the fundamental difference. Next, read Where htmx Wins, paying close attention to the examples of CRUD interfaces. These are the patterns you'll be looking for in your own applications. Finally, read Where React is Still Irreplaceable to understand the boundary cases where you might keep a client-side component.
Distilling the insights from that article and others, our rubric can be formulated as two primary questions you should ask of any React component.
Question 1: Does this component's functionality depend on server state?
This is the most critical question. Server state includes anything persisted in your database, like user data, product lists, or order information.
-
YES: The component is a candidate for an HTMX-Driven Partial.
- Examples: A data table that fetches and displays users, a form that creates a new record, pagination controls that fetch the next set of items, a search bar that queries the database.
- React equivalent: Components using
useEffectwithfetch/axiosto get data, or components using libraries like React Query or SWR.
-
NO: The component's state is purely local to the client. It's a candidate for a Client-Only Component.
- Examples: A dropdown menu, a modal dialog, a tabbed interface, a "show/hide password" toggle.
- React equivalent: Components whose
useStatecalls manage boolean flags (isOpen,isActive) or simple string/number values for UI control, without making API calls.
The article "HTMX vs Alpine.js" provides a sharp distinction between these two categories.
HTMX vs Alpine.js: When to Use Which
This article from the OpenReplay Blog focuses on the precise division of labor between server-centric and client-centric tools.
Read the sections When to Use HTMX and When to Use Alpine.js. These sections map directly to our first rubric question, providing clear use cases for each target.
Question 2: What is the required interactivity level and complexity?
This question helps refine the choice, especially for client-only components, and identifies cases where you might need to preserve a small island of high-fidelity client-side rendering.
-
Low to Medium (Typical CRUD): If the interaction is a standard CRUD operation, it confirms the choice of an HTMX-Driven Partial. The latency of a server roundtrip is perfectly acceptable for submitting a form or sorting a table.
-
High (UI Polish): If the interaction is about instant UI feedback without server data (e.g., toggling visibility), it confirms the choice of a Client-Only Component (Alpine.js). Waiting for a server response to open a dropdown menu would feel sluggish.
-
Very High / Complex (Specialized Widgets): If the component requires real-time, 60fps updates or manages a very complex internal state, it should be a Client-Only "Island".
- Examples: A rich text editor like Draft.js, a drag-and-drop interface, an interactive data visualization chart, a collaborative editing surface.
- Decision: For these cases, the latency of a server roundtrip for every small interaction is prohibitive. Your best strategy is to keep this component as a self-contained React/Preact/Svelte component that gets mounted into a specific part of your server-rendered page. We will cover this "Islands of Interactivity" pattern in more detail later.
The video from HAMY LABS provides excellent guardrails for making this call.
HTMX vs AlpineJS - Which should you use for your web app?
This video offers practical criteria for deciding between HTMX and a client-side library like Alpine.js.
First, watch the section on when to use HTMX, focusing on the three conditions presented: control over the server, the app running on server-known data, and the app not needing high-speed rendering. Next, watch the segment on when to use Alpine.js, which highlights functionality that is client-side only (like modals) and interactions with other JS libraries.
The Migration Rubric in Practice
Let's consolidate this into a practical table you can use as a cheat sheet during your migration planning.
| React Component Category | Key Characteristic | Migration Target | Litmus Test |
|---|---|---|---|
| Data Display (Tables, Lists) | Fetches and renders a collection of data from an API. | HTMX Partial | Does it use useEffect to fetch data on mount or when props like page or sortKey change? |
| Forms (Create, Edit, Search) | Gathers user input and sends it to an API endpoint. | HTMX Partial | Does it have an onSubmit handler that calls fetch or axios? Does it need to show server validation errors? |
| UI State Toggles (Modals, Tabs, Accordions) | Manages transient visibility or style state. | Client-Only (Alpine.js) | Is its state primarily useState(false) or useState('tab-1')? Does the server care if it's open or closed? |
| Page Containers / Routers | Top-level component rendered by React Router for a specific URL. | Server-Rendered Page | Is this the component associated with a <Route path="...">? |
| "Dumb" Presentational Components | Receives all its data and callbacks via props; no internal state. | Part of Parent's HTML | Does this component mostly consist of styled divs and spans? It gets absorbed into its parent's template. |
| High-Interactivity Widgets (Editors, D&D, Charts) | Manages complex, high-frequency state locally. | Client-Only "Island" | Is a server round-trip per-interaction (e.g., per keystroke or drag event) completely unfeasible? |
This rubric provides a clear path for disassembly. By applying these questions to your React components, you can methodically sort them into their new architectural buckets.
Conclusion
In this lesson, we established the foundational decision-making framework for your React-to-HTMX migration. You now have a clear, principled rubric for analyzing your existing codebase.
Key Takeaways:
- The Three Migration Targets: Server-Rendered Page, HTMX-Driven Partial, and Client-Only Component.
- The Core Question: The primary factor in classifying a component is whether it manages "meaningful" server state or transient client-side UI state.
- The Rubric: A series of questions about a component's state, data dependencies, and interaction complexity will guide it to the correct target.
- Right-Sizing Your Tools: The goal is not to eliminate JavaScript, but to move state to the server where it belongs and use lightweight client-side tools only when necessary for UI polish and complex, isolated widgets.
In our next lesson, we will put this rubric into action. You will analyze a representative CRUD feature from a typical React application and use the framework we've built today to draft a concrete, component-by-component migration plan.
Can't find a good explanation? Sign up and we'll make it for you
Sign up