# hotwired/stimulus: A Modest JavaScript Framework for HTML You Already Have

> Stimulus attaches behavior to existing HTML through data attributes instead of taking over rendering. It suits server-rendered apps that need small interactive pieces, not teams building a full client-side SPA.

**hotwired/stimulus** — A modest JavaScript framework for the HTML you already have

- Repository: https://github.com/hotwired/stimulus
- Website: https://stimulus.hotwired.dev/
- Stars: 13,104 · Forks: 441
- Language: TypeScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/hotwired-stimulus

## The problem Stimulus solves: behavior for HTML that already exists

Most JavaScript frameworks assume they own the page. They render the markup, hold the state, and re-render when things change. Stimulus starts from the opposite premise. The README describes it as a framework that "doesn't seek to take over your entire front-end" and is "not concerned with rendering HTML at all." Its job is to attach behavior to HTML that some other system already produced.

That makes it a fit for server-rendered applications where the markup arrives complete and only a few regions need interactivity: a dropdown, a form with dependent fields, a copy button. The audience is developers who already have working HTML and want to add behavior without rewriting the page as a component tree. The README frames the pairing with Turbo as "a complete solution for fast, compelling applications with a minimal amount of effort," which places Stimulus in a server-first stack rather than a client-first one.

## How the data-controller, target and action attributes drive the lifecycle

The mechanism is attribute-driven. You annotate HTML with three kinds of data attributes, and Stimulus wires them up. The README's example shows a container marked with data-controller="hello", an input marked with data-hello-target="name", a button whose data-action reads click->hello#greet, and an output span marked as a target.

The controller class declares which targets it expects via a static targets array. When the controller connects, Stimulus looks up those targets and exposes them as properties, so this.outputTarget and this.nameTarget are available inside methods. The action attribute names the event, the controller, and the method to call, which is how greet() gets invoked on click without any manual addEventListener call.

The part that matters for dynamic pages is the watching behavior. The README states that Stimulus "continuously watches the page, kicking in as soon as attributes appear or disappear," and that it works with "any update to the DOM, regardless of whether it comes from a full page load, a Turbo page change, or an Ajax request." Stimulus manages the whole lifecycle. That is the real design decision here: the framework is a MutationObserver-style layer over attributes, not a renderer. If you insert new HTML containing data-controller, the controller starts; if you remove it, the controller disconnects.

## Installing Stimulus and writing a first controller

The README says Stimulus works with any asset packaging system, and that if you prefer no build step you can drop a script tag on the page. It does not print the install commands itself; it points to the Installation Guide at stimulus.hotwired.dev/handbook/installing for detailed instructions. The package name published on npm is @hotwired/stimulus, which is what the controller import in the README uses.

With a package manager, the import path in a controller looks like this:

```js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = [ "name", "output" ]

  greet() {
    this.outputTarget.textContent =
      `Hello, ${this.nameTarget.value}!`
  }
}
```

The class extends Controller, declares its targets, and defines greet(). Note that the file is conventionally named hello_controller.js to match the data-controller="hello" value in the markup.

The corresponding HTML uses the same three attributes the README shows. The controller value, the target names and the action method all have to line up:

```html
<div data-controller="hello">
  <input data-hello-target="name" type="text">

  <button data-action="click->hello#greet">Greet</button>

  <span data-hello-target="output"></span>
</div>
```

With the controller registered, clicking the button calls greet(), which reads the input value and writes it into the output span. The README claims you can write a first controller in five minutes by following the Stimulus Handbook, and this example is small enough that the claim is plausible, though the registration step that connects the controller file to the page lives in the Installation Guide rather than the README.

## Where Stimulus is the wrong tool

Stimulus does not render HTML, and that is a deliberate boundary rather than a missing feature. If your application needs to build views from data, diff them, and keep a client-side store in sync, Stimulus gives you none of that. You would be writing the rendering yourself and using Stimulus only to bind events to the result.

The lifecycle model also has a cost. Because Stimulus reacts to attributes appearing and disappearing anywhere in the DOM, controllers can be connected and disconnected in situations you did not plan for, particularly when another library replaces a subtree. The README presents this responsiveness as a benefit, and for Turbo-driven navigation it is. In a page where a third-party script rewrites large sections of markup, it means your controllers will be torn down and re-created without an explicit call from your code.

The repository is also worth reading for what it does not contain. The README does not document rollback, version pinning guidance, or a migration path between major versions. The CHANGELOG.md file exists at the top level, so version history is tracked there rather than in the README. The most recent release listed is v3.2.2 from 2023-08-07, while the last push to the repository was on 2026-09-13, so commit activity and published releases are not moving together.

## Stimulus compared with a component framework like React

The real alternative for most teams considering Stimulus is a component framework such as React, and the difference is where the source of truth lives. React owns the markup: you describe the UI as a function of state and the library produces DOM. Stimulus owns nothing. The HTML is the source of truth, and controllers are attached to it by attribute.

That changes what you debug. With React you trace state changes through a render tree. With Stimulus you inspect the DOM and ask which controller is attached to the element in front of you, which is why the framework's own example is readable as plain HTML even before any JavaScript loads. The trade-off is that Stimulus has no opinion about how the HTML got there, so consistency across a large application depends on your server-side templates and your naming conventions rather than on a component model.

For a server-rendered Rails or similar stack that already emits HTML, this is a smaller jump than introducing a client-side renderer. For a greenfield single-page application with heavy client state, React or a comparable framework is the more direct choice, and Stimulus would leave you building the rendering layer yourself.

## Licence, maintenance and upgrade cost

Stimulus is MIT-licensed software from Basecamp, per the README, with the full text in LICENSE.md. MIT is permissive: it allows use, modification and redistribution provided the copyright notice and permission notice are retained. That is a description of the licence terms, not legal advice, and anyone with specific compliance questions should read LICENSE.md and consult their own counsel.

On maintenance, the facts are narrow. The repository is not archived, and the last push was on 2026-09-13. The most recent release shown is v3.2.2 from 2023-08-07, following v3.2.1 and v3.2.0 in late 2022. The gap between the last release and the last push is the thing to weigh: commit activity continues, but it has not produced a tagged release in the window covered here.

Upgrade cost is hard to estimate from the README alone, because it does not document version migrations or deprecations. The CHANGELOG.md at the repository root is where release-to-release changes are recorded, and the Stimulus Reference at stimulus.hotwired.dev is where API details live. For a project pinned to 3.x, the practical check before upgrading is reading CHANGELOG.md and confirming that the controller API your code uses is unchanged.

## Conclusion

Adopt hotwired/stimulus if your HTML is already rendered by a server and you need small, isolated behaviors attached to it, especially alongside Turbo. Do not adopt it if you expect the framework to render markup or manage application state; it explicitly does not render HTML. Before committing, verify the installation path that matches your build setup in the Installation Guide, and confirm the controller lifecycle behavior against the Stimulus Reference, since the README itself only points to those pages.

## FAQ

### What is hotwired/stimulus?

It is a JavaScript framework that augments existing HTML with behavior instead of rendering that HTML. The README describes it as having modest ambitions and as pairing with Turbo.

### How do I install hotwired/stimulus?

The README says it works with any asset packaging system and that you can also use a plain script tag with no build step, and it directs readers to the Installation Guide at stimulus.hotwired.dev/handbook/installing for the detailed steps.

### How do I use hotwired/stimulus in my HTML?

You add data-controller, data-*-target and data-action attributes to your markup and write a matching controller class that extends Controller and declares its targets. The README's hello example shows a container, an input target, a button action and an output target working together.

## Sources

- [hotwired/stimulus on GitHub](https://github.com/hotwired/stimulus)
- [License: MIT](https://github.com/hotwired/stimulus/blob/main/LICENSE)
- [Project website](https://stimulus.hotwired.dev/)
- [README](https://github.com/hotwired/stimulus/blob/main/README.md)
- [Releases](https://github.com/hotwired/stimulus/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hotwired-stimulus
