rails_claude_skills 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.yml +134 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +11 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.yml +129 -0
  5. data/.github/ISSUE_TEMPLATE/question.yml +90 -0
  6. data/.github/dependabot.yml +19 -0
  7. data/.github/workflows/ci.yml +77 -0
  8. data/.github/workflows/release.yml +66 -0
  9. data/.rubocop.yml +52 -0
  10. data/CHANGELOG.md +94 -0
  11. data/CLAUDE.md +332 -0
  12. data/CODE_OF_CONDUCT.md +134 -0
  13. data/CONTRIBUTING.md +580 -0
  14. data/LICENSE.txt +21 -0
  15. data/README.md +544 -0
  16. data/Rakefile +8 -0
  17. data/lib/generators/claude/agent/agent_generator.rb +71 -0
  18. data/lib/generators/claude/agent/templates/agent.md.tt +62 -0
  19. data/lib/generators/claude/command/command_generator.rb +50 -0
  20. data/lib/generators/claude/command/templates/command.md.tt +28 -0
  21. data/lib/generators/claude/commands_library/create-pr.md +27 -0
  22. data/lib/generators/claude/commands_library/dbchange.md +19 -0
  23. data/lib/generators/claude/commands_library/quality.md +20 -0
  24. data/lib/generators/claude/commands_library/stimulus.md +19 -0
  25. data/lib/generators/claude/commands_library/turbo-feature.md +17 -0
  26. data/lib/generators/claude/install/install_generator.rb +211 -0
  27. data/lib/generators/claude/install/templates/README.md.tt +59 -0
  28. data/lib/generators/claude/install/templates/USAGE +28 -0
  29. data/lib/generators/claude/install/templates/agents/api-dev.md.tt +46 -0
  30. data/lib/generators/claude/install/templates/agents/fullstack-dev.md.tt +48 -0
  31. data/lib/generators/claude/install/templates/agents/rails-developer.md.tt +40 -0
  32. data/lib/generators/claude/install/templates/settings.local.json.tt +13 -0
  33. data/lib/generators/claude/rule/rule_generator.rb +175 -0
  34. data/lib/generators/claude/rule/templates/rule.md.tt +7 -0
  35. data/lib/generators/claude/rules_library/code-style.md +37 -0
  36. data/lib/generators/claude/rules_library/database.md +47 -0
  37. data/lib/generators/claude/rules_library/hotwire.md +56 -0
  38. data/lib/generators/claude/rules_library/security.md +54 -0
  39. data/lib/generators/claude/rules_library/testing.md +47 -0
  40. data/lib/generators/claude/skill/skill_generator.rb +196 -0
  41. data/lib/generators/claude/skill/templates/SKILL.md.tt +27 -0
  42. data/lib/generators/claude/skills_library/create-task-files/SKILL.md +311 -0
  43. data/lib/generators/claude/skills_library/create-task-files/templates/bug.md +60 -0
  44. data/lib/generators/claude/skills_library/create-task-files/templates/epic.md +47 -0
  45. data/lib/generators/claude/skills_library/create-task-files/templates/issue.md +45 -0
  46. data/lib/generators/claude/skills_library/create-task-files/templates/user-story.md +57 -0
  47. data/lib/generators/claude/skills_library/minitest-testing/SKILL.md +398 -0
  48. data/lib/generators/claude/skills_library/minitest-testing/references/examples.md +889 -0
  49. data/lib/generators/claude/skills_library/plan-feature/SKILL.md +253 -0
  50. data/lib/generators/claude/skills_library/rails-api-controllers/SKILL.md +1041 -0
  51. data/lib/generators/claude/skills_library/rails-api-controllers/references/api-documentation.md +422 -0
  52. data/lib/generators/claude/skills_library/rails-api-controllers/references/serialization.md +456 -0
  53. data/lib/generators/claude/skills_library/rails-auth-with-devise/SKILL.md +191 -0
  54. data/lib/generators/claude/skills_library/rails-auth-with-devise/references/advanced.md +331 -0
  55. data/lib/generators/claude/skills_library/rails-auth-with-devise/references/api-auth.md +266 -0
  56. data/lib/generators/claude/skills_library/rails-auth-with-devise/references/omniauth.md +194 -0
  57. data/lib/generators/claude/skills_library/rails-authorization-cancancan/SKILL.md +603 -0
  58. data/lib/generators/claude/skills_library/rails-authorization-cancancan/references/api-authorization.md +543 -0
  59. data/lib/generators/claude/skills_library/rails-authorization-cancancan/references/complex-permissions.md +572 -0
  60. data/lib/generators/claude/skills_library/rails-authorization-cancancan/references/multi-tenancy.md +373 -0
  61. data/lib/generators/claude/skills_library/rails-controllers/SKILL.md +514 -0
  62. data/lib/generators/claude/skills_library/rails-debugging/SKILL.md +260 -0
  63. data/lib/generators/claude/skills_library/rails-deployment/SKILL.md +437 -0
  64. data/lib/generators/claude/skills_library/rails-deployment/references/examples.md +901 -0
  65. data/lib/generators/claude/skills_library/rails-hotwire/SKILL.md +367 -0
  66. data/lib/generators/claude/skills_library/rails-jobs/MISSION_CONTROL_SETUP.md +639 -0
  67. data/lib/generators/claude/skills_library/rails-jobs/SKILL.md +704 -0
  68. data/lib/generators/claude/skills_library/rails-mailers/SKILL.md +549 -0
  69. data/lib/generators/claude/skills_library/rails-models/SKILL.md +379 -0
  70. data/lib/generators/claude/skills_library/rails-pagination-kaminari/SKILL.md +622 -0
  71. data/lib/generators/claude/skills_library/rails-pagination-kaminari/references/api-pagination.md +523 -0
  72. data/lib/generators/claude/skills_library/rails-pagination-kaminari/references/custom-themes.md +498 -0
  73. data/lib/generators/claude/skills_library/rails-pagination-kaminari/references/performance.md +478 -0
  74. data/lib/generators/claude/skills_library/rails-views/SKILL.md +508 -0
  75. data/lib/generators/claude/skills_library/refine-requirements/SKILL.md +226 -0
  76. data/lib/generators/claude/skills_library/refine-requirements/references/examples.md +344 -0
  77. data/lib/generators/claude/skills_library/refine-requirements/references/reference.md +298 -0
  78. data/lib/generators/claude/skills_library/rspec-testing/SKILL.md +572 -0
  79. data/lib/generators/claude/skills_library/rspec-testing/references/better_specs_guide.md +273 -0
  80. data/lib/generators/claude/skills_library/rspec-testing/references/thoughtbot_patterns.md +407 -0
  81. data/lib/generators/claude/skills_library/tailwindcss/SKILL.md +371 -0
  82. data/lib/generators/claude/views/views_generator.rb +113 -0
  83. data/lib/rails_claude_skills/railtie.rb +16 -0
  84. data/lib/rails_claude_skills/version.rb +5 -0
  85. data/lib/rails_claude_skills.rb +27 -0
  86. data/sig/rails_claude_skills.rbs +4 -0
  87. metadata +199 -0
@@ -0,0 +1,367 @@
1
+ ---
2
+ name: rails-hotwire
3
+ description: Hotwire (Turbo Drive, Turbo Frames, Turbo Streams, Stimulus)
4
+ version: 1.0.0
5
+ rails_version: ">= 7.0"
6
+ tags:
7
+ - hotwire
8
+ - turbo
9
+ - stimulus
10
+ - frontend
11
+ ---
12
+
13
+ # Rails Hotwire
14
+
15
+ Hotwire is an alternative approach to building modern web applications without using much JavaScript. It consists of Turbo (Drive, Frames, Streams) and Stimulus.
16
+
17
+ ## Quick Reference
18
+
19
+ | Component | Purpose |
20
+ |-----------|---------|
21
+ | **Turbo Drive** | Fast page navigation without full reload |
22
+ | **Turbo Frames** | Decompose pages into independent contexts |
23
+ | **Turbo Streams** | Deliver page changes as HTML over WebSocket or in response to form submissions |
24
+ | **Stimulus** | JavaScript sprinkles for enhanced interactivity |
25
+
26
+ ## Turbo Drive
27
+
28
+ Turbo Drive automatically makes all link clicks and form submissions use AJAX, replacing the page body without full reload.
29
+
30
+ ```erb
31
+ <%# Turbo Drive is enabled by default in Rails 7+ %>
32
+ <%# Links and forms automatically use Turbo Drive %>
33
+
34
+ <%= link_to "Posts", posts_path %>
35
+ <%= link_to "External Site", "https://example.com", data: { turbo: false } %>
36
+
37
+ <%# Opt-out for specific elements %>
38
+ <div data-turbo="false">
39
+ <%= link_to "Normal Link", some_path %>
40
+ </div>
41
+
42
+ <%# Programmatic navigation %>
43
+ <a href="/posts" data-turbo-action="advance">Posts</a>
44
+ <a href="/posts" data-turbo-action="replace">Posts (Replace History)</a>
45
+ ```
46
+
47
+ ## Turbo Frames
48
+
49
+ Turbo Frames allow you to scope navigation and form submissions to a specific part of the page.
50
+
51
+ ### Basic Frame
52
+
53
+ ```erb
54
+ <%# app/views/posts/index.html.erb %>
55
+ <%= turbo_frame_tag "posts_list" do %>
56
+ <%= render @posts %>
57
+ <%= link_to "New Post", new_post_path %>
58
+ <% end %>
59
+
60
+ <%# app/views/posts/new.html.erb %>
61
+ <%= turbo_frame_tag "posts_list" do %>
62
+ <h2>New Post</h2>
63
+ <%= form_with model: @post do |f| %>
64
+ <%= f.text_field :title %>
65
+ <%= f.submit %>
66
+ <% end %>
67
+ <% end %>
68
+ ```
69
+
70
+ ### Lazy Loading Frames
71
+
72
+ ```erb
73
+ <%# Load content on demand %>
74
+ <%= turbo_frame_tag "post_#{post.id}", src: post_path(post), loading: :lazy do %>
75
+ <div class="loading">Loading post...</div>
76
+ <% end %>
77
+ ```
78
+
79
+ ### Targeting Frames
80
+
81
+ ```erb
82
+ <%# Target a specific frame from outside %>
83
+ <%= link_to "Edit", edit_post_path(@post), data: { turbo_frame: "modal" } %>
84
+ <%= link_to "Break out of frame", posts_path, data: { turbo_frame: "_top" } %>
85
+
86
+ <%# Turbo Frame that breaks out by default %>
87
+ <%= turbo_frame_tag "navigation", target: "_top" do %>
88
+ <%= link_to "Home", root_path %>
89
+ <% end %>
90
+ ```
91
+
92
+ ## Turbo Streams
93
+
94
+ Turbo Streams let you update multiple parts of the page in response to actions.
95
+
96
+ ### Stream Actions
97
+
98
+ ```erb
99
+ <%# app/views/posts/create.turbo_stream.erb %>
100
+
101
+ <%# Append to a container %>
102
+ <%= turbo_stream.append "posts" do %>
103
+ <%= render @post %>
104
+ <% end %>
105
+
106
+ <%# Prepend to a container %>
107
+ <%= turbo_stream.prepend "posts" do %>
108
+ <%= render @post %>
109
+ <% end %>
110
+
111
+ <%# Replace an element %>
112
+ <%= turbo_stream.replace @post do %>
113
+ <%= render @post %>
114
+ <% end %>
115
+
116
+ <%# Update content of an element %>
117
+ <%= turbo_stream.update "post_#{@post.id}" do %>
118
+ <%= render @post %>
119
+ <% end %>
120
+
121
+ <%# Remove an element %>
122
+ <%= turbo_stream.remove "post_#{@post.id}" %>
123
+
124
+ <%# Insert before/after %>
125
+ <%= turbo_stream.before "post_#{@post.id}" do %>
126
+ <div class="notice">Updated!</div>
127
+ <% end %>
128
+
129
+ <%= turbo_stream.after "post_#{@post.id}" do %>
130
+ <div class="ad">Advertisement</div>
131
+ <% end %>
132
+ ```
133
+
134
+ ### Controller Setup
135
+
136
+ ```ruby
137
+ class PostsController < ApplicationController
138
+ def create
139
+ @post = Post.new(post_params)
140
+
141
+ respond_to do |format|
142
+ if @post.save
143
+ format.turbo_stream
144
+ format.html { redirect_to @post }
145
+ else
146
+ format.turbo_stream { render :form_errors, status: :unprocessable_entity }
147
+ format.html { render :new, status: :unprocessable_entity }
148
+ end
149
+ end
150
+ end
151
+
152
+ def update
153
+ respond_to do |format|
154
+ if @post.update(post_params)
155
+ format.turbo_stream
156
+ format.html { redirect_to @post }
157
+ else
158
+ format.turbo_stream { render :form_errors, status: :unprocessable_entity }
159
+ format.html { render :edit, status: :unprocessable_entity }
160
+ end
161
+ end
162
+ end
163
+
164
+ def destroy
165
+ @post.destroy
166
+
167
+ respond_to do |format|
168
+ format.turbo_stream { render turbo_stream: turbo_stream.remove(@post) }
169
+ format.html { redirect_to posts_path }
170
+ end
171
+ end
172
+ end
173
+ ```
174
+
175
+ ### Broadcast Updates (Real-time)
176
+
177
+ ```ruby
178
+ # app/models/post.rb
179
+ class Post < ApplicationRecord
180
+ broadcasts_to ->(post) { "posts" }, inserts_by: :prepend
181
+
182
+ # Or more control
183
+ after_create_commit -> { broadcast_prepend_to "posts" }
184
+ after_update_commit -> { broadcast_replace_to "posts" }
185
+ after_destroy_commit -> { broadcast_remove_to "posts" }
186
+
187
+ # Broadcast to specific users/channels
188
+ after_create_commit -> { broadcast_prepend_to [author, "posts"], target: "posts_list" }
189
+ end
190
+ ```
191
+
192
+ ```erb
193
+ <%# Subscribe to broadcasts %>
194
+ <%= turbo_stream_from "posts" %>
195
+
196
+ <div id="posts">
197
+ <%= render @posts %>
198
+ </div>
199
+ ```
200
+
201
+ ## Stimulus
202
+
203
+ Stimulus is a modest JavaScript framework for enhancing static or server-rendered HTML.
204
+
205
+ ### Basic Controller
206
+
207
+ ```javascript
208
+ // app/javascript/controllers/clipboard_controller.js
209
+ import { Controller } from "@hotwired/stimulus"
210
+
211
+ export default class extends Controller {
212
+ static targets = ["source"]
213
+ static values = {
214
+ message: String,
215
+ count: { type: Number, default: 0 }
216
+ }
217
+
218
+ copy() {
219
+ navigator.clipboard.writeText(this.sourceTarget.value)
220
+ this.countValue++
221
+ alert(`Copied! (${this.countValue} times)`)
222
+ }
223
+ }
224
+ ```
225
+
226
+ ```erb
227
+ <div data-controller="clipboard">
228
+ <input data-clipboard-target="source" type="text" value="Copy me!">
229
+ <button data-action="click->clipboard#copy">Copy to Clipboard</button>
230
+ </div>
231
+ ```
232
+
233
+ ### Common Patterns
234
+
235
+ ```javascript
236
+ // Toggle visibility
237
+ import { Controller } from "@hotwired/stimulus"
238
+
239
+ export default class extends Controller {
240
+ static targets = ["content"]
241
+
242
+ toggle() {
243
+ this.contentTarget.classList.toggle("hidden")
244
+ }
245
+ }
246
+ ```
247
+
248
+ ```erb
249
+ <div data-controller="toggle">
250
+ <button data-action="click->toggle#toggle">Toggle</button>
251
+ <div data-toggle-target="content" class="hidden">
252
+ Hidden content
253
+ </div>
254
+ </div>
255
+ ```
256
+
257
+ ```javascript
258
+ // Form autosave
259
+ import { Controller } from "@hotwired/stimulus"
260
+
261
+ export default class extends Controller {
262
+ static targets = ["form", "status"]
263
+
264
+ async save() {
265
+ this.statusTarget.textContent = "Saving..."
266
+
267
+ const formData = new FormData(this.formTarget)
268
+ const response = await fetch(this.formTarget.action, {
269
+ method: this.formTarget.method,
270
+ body: formData,
271
+ headers: {
272
+ "X-CSRF-Token": document.querySelector("[name='csrf-token']").content
273
+ }
274
+ })
275
+
276
+ if (response.ok) {
277
+ this.statusTarget.textContent = "Saved!"
278
+ } else {
279
+ this.statusTarget.textContent = "Error saving"
280
+ }
281
+ }
282
+ }
283
+ ```
284
+
285
+ ```erb
286
+ <div data-controller="autosave">
287
+ <%= form_with model: @post, data: { autosave_target: "form", action: "change->autosave#save" } do |f| %>
288
+ <%= f.text_area :content %>
289
+ <% end %>
290
+ <span data-autosave-target="status"></span>
291
+ </div>
292
+ ```
293
+
294
+ ## Best Practices
295
+
296
+ 1. **Use Turbo Frames** for independent page sections
297
+ 2. **Use Turbo Streams** for real-time updates and multi-part updates
298
+ 3. **Keep Stimulus controllers small** and focused on one behavior
299
+ 4. **Use Stimulus values** instead of reading from the DOM
300
+ 5. **Graceful degradation** - ensure functionality works without JavaScript when possible
301
+ 6. **Use broadcasts** for real-time features (chat, notifications, etc.)
302
+ 7. **Test Turbo interactions** with system tests
303
+ 8. **Use `data-turbo-confirm`** for destructive actions
304
+ 9. **Optimize** by lazy-loading frames and using caching
305
+
306
+ ## Common Patterns
307
+
308
+ ### Modal with Turbo Frame
309
+
310
+ ```erb
311
+ <%# Layout %>
312
+ <div id="modal" class="modal">
313
+ <%= turbo_frame_tag "modal_content" %>
314
+ </div>
315
+
316
+ <%# Link that opens modal %>
317
+ <%= link_to "New Post", new_post_path, data: { turbo_frame: "modal_content" } %>
318
+
319
+ <%# app/views/posts/new.html.erb %>
320
+ <%= turbo_frame_tag "modal_content" do %>
321
+ <h2>New Post</h2>
322
+ <%= render "form", post: @post %>
323
+ <% end %>
324
+ ```
325
+
326
+ ### Inline Editing
327
+
328
+ ```erb
329
+ <%# Show mode %>
330
+ <%= turbo_frame_tag "post_#{@post.id}" do %>
331
+ <h2><%= @post.title %></h2>
332
+ <%= link_to "Edit", edit_post_path(@post) %>
333
+ <% end %>
334
+
335
+ <%# Edit mode %>
336
+ <%# app/views/posts/edit.html.erb %>
337
+ <%= turbo_frame_tag "post_#{@post.id}" do %>
338
+ <%= form_with model: @post do |f| %>
339
+ <%= f.text_field :title %>
340
+ <%= f.submit "Save" %>
341
+ <% end %>
342
+ <% end %>
343
+ ```
344
+
345
+ ### Pagination with Turbo Frames
346
+
347
+ ```erb
348
+ <%= turbo_frame_tag "posts" do %>
349
+ <%= render @posts %>
350
+ <%= link_to "Load More", posts_path(page: @next_page) %>
351
+ <% end %>
352
+ ```
353
+
354
+ ## Troubleshooting
355
+
356
+ - **Frame not updating**: Check that frame IDs match
357
+ - **Form not working**: Ensure you're using `form_with` not `form_for`
358
+ - **Turbo Drive issues**: Use `data-turbo="false"` to opt-out
359
+ - **Broadcasts not working**: Check ActionCable is configured
360
+ - **Stimulus controller not connecting**: Check console for errors, verify data-controller name
361
+
362
+ ## References
363
+
364
+ - [Turbo Handbook](https://turbo.hotwired.dev/handbook/introduction)
365
+ - [Stimulus Handbook](https://stimulus.hotwired.dev/handbook/introduction)
366
+ - [Hotwire Homepage](https://hotwired.dev/)
367
+ - [Turbo Rails Gem](https://github.com/hotwired/turbo-rails)