From obie-skills
Applies Better Stimulus best practices for writing maintainable, reusable StimulusJS controllers following SOLID principles. Covers configurable controllers, Values API, declarative events, and focused architecture.
How this skill is triggered — by the user, by Claude, or both
Slash command
/obie-skills:better-stimulusThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Apply opinionated best practices from [betterstimulus.com](https://betterstimulus.com/) when writing or refactoring Stimulus controllers. These patterns emphasize code reusability, proper separation of concerns, and SOLID design principles.
Apply opinionated best practices from betterstimulus.com when writing or refactoring Stimulus controllers. These patterns emphasize code reusability, proper separation of concerns, and SOLID design principles.
Invoke this skill when:
Externalize hardcoded values into data attributes rather than embedding them in controller logic.
Bad:
toggle() {
this.element.classList.toggle("active")
}
Good:
static classes = ["active"]
toggle() {
this.element.classList.toggle(this.activeClass)
}
<div data-controller="toggle" data-toggle-active-class="active"></div>
Store controller state in Stimulus values, not instance properties, to leverage reactivity and DOM persistence.
Bad:
connect() {
this.count = 0
}
Good:
static values = { count: Number }
countValueChanged(count) {
this.updateDisplay()
}
Each controller should have one reason to change. Split controllers that mix concerns.
Ask: "What would cause this controller to change?" If multiple unrelated reasons, split it.
Use connect() for:
Don't use connect() for:
data-action)Use data-action attributes instead of addEventListener() to let Stimulus manage lifecycle.
Bad:
connect() {
document.addEventListener("click", this.handler.bind(this))
}
Good:
<div data-action="click@document->controller#handler"></div>
See: references/architecture.md
[name]ValueChanged)See: references/state-management.md
connect() for third-party library initializationconnect() with disconnect() for cleanupconnect() with state setupteardown() for Turbo-specific cleanupSee: references/lifecycle.md
Three approaches:
Choose based on relationship:
See: references/events-and-interaction.md
See: references/solid-principles.md
<template> to restore DOM staterequestSubmit() not submit() for formsSee: references/dom-and-turbo.md
handleError() methodSee: references/error-handling.md
static values = {
url: String,
count: Number,
enabled: Boolean,
items: Array,
config: Object
}
<!-- Element events -->
<div data-action="click->controller#method">
<!-- Global events -->
<div data-action="resize@window->controller#layout">
<div data-action="keydown@document->controller#handleKey">
<!-- Multiple actions -->
<div data-action="click->ctrl1#method1 click->ctrl2#method2">
// Dispatch
const event = new CustomEvent('name:action', {
bubbles: true,
detail: { key: 'value' }
})
this.element.dispatchEvent(event)
// Listen
data-action="name:action->controller#handler"
<div data-controller="parent"
data-parent-child-outlet=".child">
<div class="child" data-controller="child"></div>
</div>
static outlets = ['child']
this.childOutlets.forEach(outlet => outlet.method())
connect() // Element connected to DOM
disconnect() // Element removed from DOM
[name]TargetConnected(element) // Target added
[name]TargetDisconnected(element) // Target removed
[name]ValueChanged(value, oldValue) // Value changed
[name]OutletConnected(outlet) // Outlet connected
[name]OutletDisconnected(outlet) // Outlet disconnected
When writing a new controller:
When refactoring:
connect() with state setup and event listenersaddEventListener() without proper cleanup.bind() separately in connect and disconnectsubmit() instead of requestSubmit()All patterns in this skill come from betterstimulus.com, an opinionated collection of StimulusJS best practices.
For detailed explanations and examples, see:
references/architecture.md - Controller design patternsreferences/state-management.md - Values API usagereferences/lifecycle.md - Lifecycle best practicesreferences/events-and-interaction.md - Communication patternsreferences/solid-principles.md - SOLID design principlesreferences/dom-and-turbo.md - DOM manipulation and Turboreferences/error-handling.md - Error managementnpx claudepluginhub joshuarweaver/cascade-code-general-misc-2 --plugin obie-skillsApplies opinionated StimulusJS best practices for writing, reviewing, and refactoring Stimulus controllers. Covers architecture, mixins, state management with Values API, and integration with Hotwire/Turbo.
Creates and refactors Stimulus controllers using Hotwire conventions, design patterns, targets/values, action handling, and JavaScript best practices for interactive UIs.
Covers Stimulus controller fundamentals: lifecycle hooks, values, targets, outlets, action parameters, keyboard events, and architecture patterns. Best for Stimulus API questions outside Hotwire domains.