stimulus — stimulus setup for rails applications stimulus, easy_notes, community, stimulus setup for rails applications, ide skills, Claude Code, Cursor, Windsurf

v1.0.0
GitHub

About this Skill

Perfect for Frontend Agents needing efficient JavaScript framework integration for Rails applications. Stimulus is a modest JavaScript framework that connects JavaScript to the DOM via data attributes, designed to augment HTML with just enough behavior.

Features

Connects JavaScript to the DOM via data attributes
Keeps HTML as the source of truth for application behavior
Supports Rails applications with efficient and modest interactivity
Follows best practices as outlined in Stimulus version 3.2.2
References the official Stimulus documentation at https://stimulus.hotwired.dev/

# Core Topics

sandnap sandnap
[0]
[0]
Updated: 3/8/2026

Agent Capability Analysis

The stimulus skill by sandnap is an open-source community AI agent skill for Claude Code and other IDE workflows, helping agents execute tasks with better context, repeatability, and domain-specific guidance. Optimized for stimulus setup for rails applications.

Ideal Agent Persona

Perfect for Frontend Agents needing efficient JavaScript framework integration for Rails applications.

Core Value

Empowers agents to augment HTML with behavior using data attributes, keeping HTML as the source of truth, and leveraging Stimulus version 3.2.2 for efficient interactivity via the DOM.

Capabilities Granted for stimulus

Augmenting Rails application HTML with interactive behavior
Connecting JavaScript to the DOM via data attributes
Keeping HTML as the source of truth for Rails application development

! Prerequisites & Limits

  • Requires JavaScript and HTML knowledge
  • Specifically designed for Rails applications
  • Version compatibility limited to Stimulus version 3.2.2
Labs Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

stimulus

Install stimulus, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command setup.

SKILL.md
Readonly

Stimulus Best Practices for Rails Applications

Rule updated on 12/15/2025 to Stimulus version 3.2.2

Stimulus is a modest JavaScript framework designed to augment your HTML with just enough behavior. It connects JavaScript to the DOM via data attributes, keeping your HTML as the source of truth.

For full reference see https://stimulus.hotwired.dev/

Core Concepts

ConceptPurposeData Attribute
ControllerJavaScript class that adds behaviordata-controller="name"
TargetImportant elements referenced in JSdata-name-target="targetName"
ActionEvent handlers connecting DOM to methodsdata-action="event->name#method"
ValueReactive data stored in HTMLdata-name-value-name="value"
ClassCSS classes toggled by the controllerdata-name-class-name="class"
OutletReferences to other controllersdata-name-outlet-name="selector"

When to Use Stimulus

Use Stimulus for:

  • Toggle visibility (dropdowns, modals, accordions)
  • Form enhancements (character counters, auto-submit, validation UI)
  • Copy to clipboard
  • Keyboard shortcuts
  • Animations and transitions
  • Client-side filtering/sorting (small datasets)
  • Debounced input handlers
  • Any behavior that doesn't require server data

Don't use Stimulus for:

  • Data that should come from the server (use Turbo Streams instead)
  • Complex state management (consider if your approach is right)
  • Things Turbo already handles (form submission, navigation)

Controller Structure

File Naming & Location

Controllers that live in app/javascript/controllers/ and follow the naming convention below are automatically registered.

File NameController NameHTML Reference
hello_controller.jsHelloControllerdata-controller="hello"
clipboard_controller.jsClipboardControllerdata-controller="clipboard"
user_form_controller.jsUserFormControllerdata-controller="user-form"

Basic Controller Template

javascript
1import { Controller } from "@hotwired/stimulus" 2 3export default class extends Controller { 4 static targets = ["input", "output"] 5 static values = { url: String, count: Number, active: Boolean } 6 static classes = ["hidden", "active"] 7 8 connect() { 9 // Called when controller is connected to DOM 10 } 11 12 disconnect() { 13 // Called when controller is removed from DOM 14 // Clean up event listeners, timers, etc. 15 } 16 17 // Action methods 18 toggle() { 19 this.outputTarget.classList.toggle(this.hiddenClass) 20 } 21}

Targets

Targets provide named references to important elements within the controller's scope.

Defining Targets

javascript
1export default class extends Controller { 2 static targets = ["input", "submit", "error"] 3 4 validate() { 5 if (this.inputTarget.value.length < 3) { 6 this.errorTarget.textContent = "Too short" 7 this.submitTarget.disabled = true 8 } 9 } 10}

HTML Usage

erb
1<div data-controller="form"> 2 <input data-form-target="input" data-action="input->form#validate"> 3 <span data-form-target="error"></span> 4 <button data-form-target="submit">Submit</button> 5</div>

Target Properties

PropertyReturnsExample
this.inputTargetFirst matching element (or error)Single element
this.inputTargetsArray of all matching elements[el1, el2, el3]
this.hasInputTargetBoolean if target existstrue / false

Values

Values are reactive data attributes that automatically sync between HTML and JavaScript.

Defining Values

javascript
1export default class extends Controller { 2 static values = { 3 url: String, 4 count: Number, 5 active: Boolean, 6 config: Object, 7 items: Array, 8 } 9 10 countValueChanged(value, previousValue) { 11 // Called automatically when count value changes 12 console.log(`Count changed from ${previousValue} to ${value}`) 13 } 14}

HTML Usage

erb
1<div data-controller="counter" 2 data-counter-count-value="0" 3 data-counter-url-value="<%= api_path %>" 4 data-counter-config-value="<%= { limit: 10 }.to_json %>"> 5</div>

Value Benefits

  • Reactive: Changes trigger *ValueChanged callbacks
  • Type coercion: Automatic conversion to declared type
  • Default values: static values = { count: { type: Number, default: 0 } }
  • HTML as source of truth: State is visible in the DOM

Actions

Actions connect DOM events to controller methods.

Action Syntax

data-action="event->controller#method"

Common Patterns

erb
1<!-- Click event (default for buttons) --> 2<button data-action="dropdown#toggle">Menu</button> 3 4<!-- Explicit event --> 5<input data-action="input->search#filter"> 6 7<!-- Multiple actions --> 8<input data-action="focus->form#highlight blur->form#unhighlight"> 9 10<!-- Keyboard events with filters --> 11<input data-action="keydown.enter->form#submit keydown.escape->form#cancel"> 12 13<!-- Window/document events --> 14<div data-controller="modal" data-action="keydown.escape@window->modal#close"> 15 16<!-- Form events --> 17<form data-action="submit->form#validate">

Event Modifiers

ModifierEffect
:preventCalls event.preventDefault()
:stopCalls event.stopPropagation()
:selfOnly fires if target is element
:onceRemoves listener after first fire
erb
1<a href="#" data-action="click->nav#toggle:prevent">Toggle</a>

Classes

Classes let you reference CSS classes from your controller without hardcoding them.

Defining Classes

javascript
1export default class extends Controller { 2 static classes = ["active", "hidden", "loading"] 3 4 toggle() { 5 this.element.classList.toggle(this.activeClass) 6 } 7 8 load() { 9 if (this.hasLoadingClass) { 10 this.element.classList.add(this.loadingClass) 11 } 12 } 13}

HTML Usage

erb
1<div data-controller="toggle" 2 data-toggle-active-class="bg-blue-500 text-white" 3 data-toggle-hidden-class="hidden"> 4</div>

Lifecycle Callbacks

javascript
1export default class extends Controller { 2 initialize() { 3 // Called once when controller is first instantiated 4 // Use for one-time setup that doesn't depend on DOM 5 } 6 7 connect() { 8 // Called each time controller connects to DOM 9 // Set up event listeners, fetch data, start timers 10 } 11 12 disconnect() { 13 // Called when controller disconnects from DOM 14 // ALWAYS clean up: remove listeners, clear timers, abort fetches 15 } 16}

Cleanup Example

javascript
1export default class extends Controller { 2 connect() { 3 this.interval = setInterval(() => this.refresh(), 5000) 4 this.abortController = new AbortController() 5 } 6 7 disconnect() { 8 clearInterval(this.interval) 9 this.abortController.abort() 10 } 11 12 async refresh() { 13 const response = await fetch(this.urlValue, { 14 signal: this.abortController.signal, 15 }) 16 // ... 17 } 18}

Common Controller Patterns

Toggle Controller

javascript
1// toggle_controller.js 2import { Controller } from "@hotwired/stimulus" 3 4export default class extends Controller { 5 static targets = ["content"] 6 static classes = ["hidden"] 7 8 toggle() { 9 this.contentTarget.classList.toggle(this.hiddenClass) 10 } 11 12 show() { 13 this.contentTarget.classList.remove(this.hiddenClass) 14 } 15 16 hide() { 17 this.contentTarget.classList.add(this.hiddenClass) 18 } 19}

Clipboard Controller

javascript
1// clipboard_controller.js 2import { Controller } from "@hotwired/stimulus" 3 4export default class extends Controller { 5 static targets = ["source"] 6 static values = { successDuration: { type: Number, default: 2000 } } 7 8 copy() { 9 navigator.clipboard.writeText(this.sourceTarget.value) 10 this.showCopiedState() 11 } 12 13 showCopiedState() { 14 this.element.dataset.copied = true 15 setTimeout(() => delete this.element.dataset.copied, this.successDurationValue) 16 } 17}

Debounce Controller

javascript
1// search_controller.js 2import { Controller } from "@hotwired/stimulus" 3 4export default class extends Controller { 5 static targets = ["input", "form"] 6 static values = { delay: { type: Number, default: 300 } } 7 8 search() { 9 clearTimeout(this.timeout) 10 this.timeout = setTimeout(() => { 11 this.formTarget.requestSubmit() 12 }, this.delayValue) 13 } 14 15 disconnect() { 16 clearTimeout(this.timeout) 17 } 18}

Integration with Turbo

Persisting Controllers Across Navigation

Turbo Drive preserves <head> but replaces <body>. Controllers on body elements disconnect and reconnect. Use values to persist state:

erb
1<!-- State survives Turbo navigation because it's in HTML --> 2<div data-controller="sidebar" data-sidebar-open-value="true">

Responding to Turbo Events

javascript
1export default class extends Controller { 2 connect() { 3 document.addEventListener("turbo:before-cache", this.cleanup) 4 } 5 6 disconnect() { 7 document.removeEventListener("turbo:before-cache", this.cleanup) 8 } 9 10 cleanup = () => { 11 // Reset state before Turbo caches the page 12 this.element.classList.remove("is-active") 13 } 14}

Working with Turbo Frames

javascript
1export default class extends Controller { 2 connect() { 3 this.element.addEventListener("turbo:frame-load", this.onFrameLoad) 4 } 5 6 onFrameLoad = (event) => { 7 // React to frame content loading 8 this.updateUI() 9 } 10}

Best Practices Summary

  1. Keep controllers small — One responsibility per controller (< 100 lines ideally)
  2. Use values for state — Don't store state in instance variables; keep it in data attributes
  3. Always clean up — Clear timers, abort fetches, remove listeners in disconnect()
  4. Prefer HTML over JS — Use data attributes to configure behavior, not JavaScript
  5. Name actions clearlytoggle, submit, validate not handleClick, onClick
  6. Use targets over querySelector — More explicit and self-documenting
  7. Compose with multiple controllers — Combine small controllers rather than building monoliths
  8. Let Turbo handle server communication — Stimulus is for client-side behavior only

Anti-Patterns to Avoid

Don'tDo Instead
Store state in instance variablesUse values (static values = {})
Use querySelector in controllersUse targets (static targets = [])
Hardcode CSS classesUse classes (static classes = [])
Forget to clean up in disconnectAlways clean up timers, listeners, etc.
Make controllers too largeSplit into multiple focused controllers
Use Stimulus for data fetchingUse Turbo Frames/Streams for server data
Duplicate controller logicExtract shared behavior to base class

FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is stimulus?

Perfect for Frontend Agents needing efficient JavaScript framework integration for Rails applications. Stimulus is a modest JavaScript framework that connects JavaScript to the DOM via data attributes, designed to augment HTML with just enough behavior.

How do I install stimulus?

Run the command: npx killer-skills add sandnap/easy_notes. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

What are the use cases for stimulus?

Key use cases include: Augmenting Rails application HTML with interactive behavior, Connecting JavaScript to the DOM via data attributes, Keeping HTML as the source of truth for Rails application development.

Which IDEs are compatible with stimulus?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for stimulus?

Requires JavaScript and HTML knowledge. Specifically designed for Rails applications. Version compatibility limited to Stimulus version 3.2.2.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add sandnap/easy_notes. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use stimulus immediately in the current project.

Related Skills

Looking for an alternative to stimulus or another community skill for your workflow? Explore these related open-source skills.

View All

widget-generator

Logo of f
f

f.k.a. Awesome ChatGPT Prompts. Share, discover, and collect prompts from the community. Free and open source — self-host for your organization with complete privacy.

149.6k
0
AI

flags

Logo of vercel
vercel

flags is a Next.js feature management skill that enables developers to efficiently add or modify framework feature flags, streamlining React application development.

138.4k
0
Browser

zustand

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
AI

data-fetching

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
AI