skills/stimulus-controllers/SKILL.md
Create and register Stimulus controllers for interactive JavaScript features. Use when adding client-side interactivity, dynamic UI updates, or when the user mentions Stimulus controllers or JavaScript behavior.
npx skillsauth add rolemodel/rolemodel-skills stimulus-controllersInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Stimulus controllers provide modular JavaScript functionality connected to HTML via data attributes. After creating a new controller, you must register it in the index.js file.
Create a new controller in app/javascript/controllers/:
// app/javascript/controllers/example_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["element"]
static values = { name: String }
connect() {
// Called when controller is connected to DOM
}
disconnect() {
// Called when controller is disconnected from DOM
}
// Action methods
handleClick(event) {
event.preventDefault()
// Your logic here
}
}
CRITICAL: After creating a new controller, run:
bin/rails stimulus:manifest:update
This automatically updates app/javascript/controllers/index.js to register your controller.
Manual Registration (if needed):
import ExampleController from "./example_controller"
application.register("example", ExampleController)
Controller name in HTML uses kebab-case: data-controller="example"
Connect the controller to HTML elements:
.container data-controller="example" data-example-name-value="test"
button data-action="click->example#handleClick" Click Me
div data-example-target="element" Target Element
example_controller.js (snake_case)export default class extends Controller"example" (kebab-case)data-controller="example" (kebab-case)bulk_submit_controller.js → "bulk-submit"Reference specific DOM elements:
static targets = ["input", "output"]
// Access in methods:
this.inputTarget // First matching element
this.inputTargets // All matching elements
this.hasInputTarget // Boolean check
Type-safe data attributes:
static values = {
url: String,
count: Number,
active: Boolean,
items: Array,
config: Object
}
// Access in methods:
this.urlValue
this.countValue
// Watch for changes:
urlValueChanged(newUrl, oldUrl) {
// Called when value changes
}
Connect events to methods:
<!-- Basic action -->
data-action="click->example#save"
<!-- Multiple actions -->
data-action="click->example#save submit->example#submit"
<!-- Custom events -->
data-action="example:refresh->example#reload"
<!-- Event modifiers -->
data-action="submit->example#save:prevent"
Manage CSS classes:
static classes = ["active", "hidden"]
// Use in methods:
this.element.classList.add(this.activeClass)
this.element.classList.remove(this.hiddenClass)
export default class extends Controller {
static targets = ["form", "submit"]
validate() {
const isValid = this.formTarget.checkValidity()
this.submitTarget.disabled = !isValid
}
}
export default class extends Controller {
static targets = ["content"]
static classes = ["hidden"]
toggle() {
this.contentTarget.classList.toggle(this.hiddenClass)
}
}
export default class extends Controller {
static values = { url: String }
async refresh() {
const response = await fetch(this.urlValue)
const html = await response.text()
this.element.innerHTML = html
}
}
Test Stimulus controllers in system specs:
it 'handles interaction', :js do
visit page_path
click_button 'Toggle'
expect(page).to have_css('[data-controller="example"]')
end
Controller not working?
index.jsbin/rails stimulus:manifest:update:js tag)Targets not found?
static targets matches HTMLhasXxxTarget to verify existence before accessingtesting
Verify what Ruby versions actually exist and install a specific Ruby via rbenv. Use BEFORE asserting that any Ruby version does or doesn't exist (e.g., "Ruby 4.0 isn't out yet", "the latest Ruby is 3.x", "Ruby X.Y.Z doesn't exist"). Also use when the user asks "what's the latest Ruby", "is Ruby X out", "does Ruby X.Y exist", "install Ruby", "switch to Ruby X", "what Ruby is installed", or mentions a specific Ruby version you're unsure about. Claude's training data may be out of date — run `check.sh` first.
development
Trace code through the stack — upward to entry points, downward to data, or laterally across boundaries. Use when the user asks "where does this get called from", "what calls this method", "trace this through the stack", "how does this request flow", "where does this data come from", "follow this through the code", or pastes/selects a piece of code and wants to understand where it fits in the larger system.
tools
Pick the single highest-priority unresolved Sentry issue and hand it off to a fixer skill. Use when triaging Sentry errors, running automated issue triage, or when asked to fix the top Sentry issue in a project.
tools
Find and fix issues from Sentry using MCP. Use when asked to fix Sentry errors, debug production issues, investigate exceptions, or resolve bugs reported in Sentry. Methodically analyzes stack traces, breadcrumbs, traces, and context to identify root causes.