|
Navigation
Search
|
Intro to Hotwire: HTML over the wire
Wednesday December 31, 2025. 10:00 AM , from InfoWorld
If you’ve been watching the JavaScript landscape for a while, you’ve likely noticed the trend toward simplicity in web application development. An aspect of this trend is leveraging HTML, REST, and HATEOAS (hypermedia as the engine of application state) to do as much work as possible. In this article, we’ll look at Hotwire, a collection of tools for building single-page-style applications using HTML over the wire.
Hotwire is a creative take on front-end web development. It’s also quite popular, with more than 33,000 stars on GitHub and 493,000 weekly NPM downloads as of this writing. Hotwire: An alternative to HTMX Hotwire is built on similar principles to HTMX and offers an alternative approach to using HTML to drive the web. Both projects strive to eliminate boilerplate JavaScript and let developers do more with simple markup. Both embrace HATEOAS and the original form of REST. The central insight here is that application markup can contain both the state (or data) and the structure of how data is to be displayed. This makes it possible to sidestep the unnecessary logistics of marshaling JSON at both ends. This concept isn’t new—in fact, it is the essence of representational state transfer (REST). Instead of converting to a special data format (JSON) on the server, then sending that over to the client where it is converted for the UI (HTML), you can just have the server send the HTML. Technologies like HTMX and Hotwire streamline the process, making it palatable for developers and users who are acclimated to the endless micro-interactions spawned by Ajax. Hotwire has three primary JavaScript components, but we are mainly interested in the first two: Turbo: Allows for fine-grained control of page updates. Stimulus: A concise library for client-side interactivity. Native: A library for creating iOS- and Android-native apps from Turbo and Stimulus. In this article, we will look at Turbo and Stimulus. Turbo has several components that make interactivity with HTML more powerful: Turbo Drive avoids full page reloads for links and form submits. Turbo Frame lets you define areas of the UI that can be loaded independently (including lazy loading). Turbo Streams allows for arbitrarily updating specific page segments (using WebSockets, server-side events, or a form response). Turbo Drive: Merging pages, not loading pages In standard HTML, when you load a page, it completely obliterates the existing content and paints all the content anew as it arrives from the server. This is incredibly inefficient and makes for a bad user experience. Turbo Drive takes a different approach by dropping in a JavaScript link, which merges the page contents instead of reloading them. Think of merging like diffing the current page with the coming page. The header information is updated rather than being wholesale replaced. Modern Turbo even “morphs” the and elements, providing a much smoother transition. (For obvious reasons, this approach is especially effective for page reloads.) All you have to do is include the turbo script in your page: It is also important to point out that browser actions like back, forward, and reload all work normally. Merging is a low-cost, low-risk way of improving page navigation and reloads in web pages. Turbo Frames: Granular UI development The basic idea in Frames is to decompose the layout of a web page into elements. You then update these frames piecemeal, and only as needed. The overall effect is like using JSON responses to drive reactive updates to the UI, but in this case we are using HTML fragments. Take this page as an example: Links that change the entire page Thimbleberry (Rubus parviflorus) A delicate, native berry with large, soft leaves. Edit this description Found a large patch by the creek. The berries are very fragile.... Here we have a top navigation pane with links that will affect the entire page (useable with Turbo Drive). Then there are two interior elements that can be modified in place, without the entire page reload. The elements capture events within them. So, when you click the link to edit the field notes, the server can respond with a chunk to provide an editable form: Field Notes Found a large patch by the creek. The berries are very fragile. Add a new note: This chunk would be rendered as a live form. The user can make updates and submit the new data, and the server would reply with a new fragment containing the updated frame: Field Notes Found a large patch by the creek. The berries are very fragile. Just saw a bear! Add a new note: Turbo takes the ID on the arriving frame content and ensures it replaces the same frame on the page (so it is essential that the server puts the correct ID on the fragments it sends). Turbo is smart enough to extract and place only the relevant fragment, even if an entire page is received from the server. Turbo Streams: Compound updates Turbo Drive is a simple and effective mechanism for handling basic server interactions. Sometimes, we need more powerful updates that interact with multiple portions of the page, or that are triggered from the server side. For that, Turbo has Streams. The basic idea is that the server sends a stream of fragments, each with the ID of the part of the UI that will change, along with the content needed for the change. For example, we might have a stream of updates for our wilderness log: Just saw a Fox! 4 Notes Add a new note: Here, we are using streams instead of frames to handle the notes update. The idea is that each section that needs updating, like the new note, the note counter, and the live form section receive their content as a stream item. Notice the stream items each has an “action” and a “target” to describe what will happen. Streams can target multiple elements by using the targets (notice the plural here) and a CSS selector to identify the elements that will be affected. Turbo will automatically handle responses from the server (like for a form response) that contain a collection of elements, placing them correctly into the UI. This will handle many multi-change requirements. Notice also that in this case, when you are using streams, you don’t need to use a. In fact, mixing the two is not recommended. As a rule of thumb, you should use frames for simplicity whenever you can, and upgrade to streams (and dispense with frames) only when you need to. Reusability A key benefit to both Turbo Frames and Turbo Streams is being able to reuse the server-side templates that render UI elements both initially and for updates. You simply decompose your server-side template (like RoR templates or Thymeleaf or Kotlin DSL or Pug—whatever tool you are using) into the same chunks the UI needs. Then you can just use them to render both the initial and ongoing states of those chunks. For example, here’s a simple Pug template that could be used as part of the whole page or to generate update chunks: turbo-frame#field_notes h2 Field Notes //- 1. The List: Iterates over the 'notes' array div#notes_list each note in notes div(id=`note_${note.id}`)= note.content //- 2. The Form: On submission, this fragment is re-rendered - by the server, which includes a fresh, empty form. form(action='/berries/thimbleberry/notes', method='post') div label(for='note_content') Add a new note: div //- We just need the 'name' attribute for the server textarea(id='note_content', name='content') div input(type='submit', value='Save note') Server push It’s also possible to provide background streams of events using the element: This element automatically connects to a back-end API for SSE or WebSocket updates. These broadcast updates would have the same structure as before: Which will automatically connect to a back end API for SSE or WebSocket updates. These broadcast updates would have the same structure as before: Also found Salmonberries here! Client-side magic with Stimulus HTMX is sometimes paired with Alpine.js, with the latter giving you fancier front-end interactivity like accordions, drag-and-drop functionality, and so forth. In Hotwire, Stimulus serves the same purpose. In Stimulus, you use HTML attributes to connect elements to “controllers,” which are chunks of JavaScript functionality. For example, if we wanted to provide a clipboard copy button, we could do something like this: Thimbleberry (Rubus parviflorus) A delicate, native berry with large, soft leaves. Copy Name Notice the data-contoller attribute. That links the element to the clipboard controller. Stimulus uses a filename convention, and in this case, the file would be: clipboard_controller.js, with contents something like this: import { Controller } from '@hotwired/stimulus' export default class extends Controller { // Connects to data-clipboard-target='source' // and data-clipboard-target='feedback' static targets = [ 'source', 'feedback' ] // Runs when data-action='click->clipboard#copy' is triggered copy() { // 1. Get text from the 'source' target const textToCopy = this.sourceTarget.textContent // 2. Use the browser's clipboard API navigator.clipboard.writeText(textToCopy) // 3. Update the 'feedback' target to tell the user this.feedbackTarget.textContent = 'Copied!' // 4. (Optional) Reset the button after 2 seconds setTimeout(() => { this.feedbackTarget.textContent = 'Copy Name' }, 2000) } } The static target member provides those elements to the controller to work with, based on the data-clipboard-target attribute in the markup. The controller then uses simple JavaScript to perform the clipboard copy and a timed message to the UI. The basic idea is you keep your JavaScript nicely isolated in small controllers that are linked into the markup as needed. This lets you do whatever extra client-side magic to enhance the server-side work in a manageable way. Conclusion The beauty of Hotwire is in doing most of what you need with a very small footprint. It does 80% of the work with 20% of the effort. Hotwire doesn’t have the extravagant power of a full-blown framework like React or a full-stack option like Next, but it gives you most of what you’ll need for most development scenarios. Hotwire also works with any back end with typical technologies.
https://www.infoworld.com/article/4100499/intro-to-hotwire-interactive-javascript-built-from-html.ht
Related News |
25 sources
Current Date
Dec, Wed 31 - 12:25 CET
|







