Skip to main content
0 percent read
Hotwire and Stimulus: composable JS without the bundle guilt

Hotwire and Stimulus: composable JS without the bundle guilt

2 min read · by admin

Share

Reactions

## Outline


- Why Rails doubled down on HTML-first delivery.
- Turbo Drive: respect the round trip; avoid client-only state across pages.
- Stimulus: one job per controller; targets and values over DOM queries.
- Lifecycle (`connect` / `disconnect`) as part of your public API.
- Progressive enhancement as default posture.


## Draft


Hotwire exists because **shipping HTML from the server** still beats defaulting every screen to a client archipelago. You can get snappy UX with a **small** JavaScript surface—without standing up a second application that re-implements validation for sport.

The failure mode is not Turbo. It is **Stimulus sprawl**: controllers that grow until you have rebuilt the SPA you said you did not want, except with fewer guardrails.

### Turbo Drive still goes to the server


Drive makes many navigations feel lighter than a full document reload. Latency does not disappear—you still wait on Ruby, the database, and whatever caches you own. The win is smoother paint and fewer jarring full resets. When a feature acts weird after “go somewhere and come back,” ask whether you relied on **client-only state** that Turbo never promised to preserve.

Use each request as a reason to send **meaningful HTML**, and use HTTP caching where it is actually safe—not everywhere by reflex.

### Stimulus works when controllers stay small


Name behaviors, not page zones: **toggle**, **copy**, **dismiss**, **sync**. If one controller reaches into three unrelated parts of the DOM, split it or pull a tiny ES module into `connect` instead of chaining `querySelector` like it is 2014.

Prefer **`data-*-target`** and **`data-*-value`** so the markup documents the contract. Designers and QA can read the HTML and know what attaches where.


### Lifecycle is not optional polish


Register listeners in **`connect`** and tear them down in **`disconnect`**. Skipping teardown is how you get the ticket: “Only breaks after I visit the page twice.”

### Progressive enhancement is still a flex


The story should read without JavaScript. Layer Stimulus for niceties—dropdowns, copy-to-clipboard, theme persistence—not as a paywall on the words.

Enjoyed this post?

Share it with a teammate, browse more posts, or explore related tags to keep learning.

New posts by email

Get notified when we publish—unsubscribe anytime.

We only use your address for this list.

Selected from similar categories and overlapping topics.

More in this category

Keep exploring Tutorials guides and articles.