plutonium 0.44.1 → 0.45.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/skill.md +88 -11
  3. data/.claude/skills/plutonium-assets/SKILL.md +1 -1
  4. data/.claude/skills/plutonium-controller/SKILL.md +6 -2
  5. data/.claude/skills/plutonium-create-resource/SKILL.md +1 -1
  6. data/.claude/skills/plutonium-definition/SKILL.md +445 -53
  7. data/.claude/skills/plutonium-definition-actions/SKILL.md +2 -2
  8. data/.claude/skills/plutonium-definition-query/SKILL.md +2 -2
  9. data/.claude/skills/plutonium-forms/SKILL.md +6 -2
  10. data/.claude/skills/plutonium-installation/SKILL.md +3 -3
  11. data/.claude/skills/plutonium-interaction/SKILL.md +3 -3
  12. data/.claude/skills/plutonium-invites/SKILL.md +1 -1
  13. data/.claude/skills/plutonium-model/SKILL.md +228 -55
  14. data/.claude/skills/plutonium-nested-resources/SKILL.md +9 -2
  15. data/.claude/skills/plutonium-package/SKILL.md +3 -3
  16. data/.claude/skills/plutonium-policy/SKILL.md +6 -2
  17. data/.claude/skills/plutonium-portal/SKILL.md +97 -59
  18. data/.claude/skills/plutonium-profile/SKILL.md +2 -2
  19. data/.claude/skills/plutonium-rodauth/SKILL.md +1 -1
  20. data/.claude/skills/plutonium-theming/SKILL.md +1 -1
  21. data/.claude/skills/plutonium-views/SKILL.md +2 -2
  22. data/CHANGELOG.md +15 -0
  23. data/app/assets/plutonium.css +1 -1
  24. data/gemfiles/rails_7.gemfile.lock +1 -1
  25. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  26. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  27. data/lib/generators/pu/invites/install_generator.rb +2 -2
  28. data/lib/generators/pu/invites/templates/packages/invites/app/views/invites/user_invitations/show.html.erb.tt +7 -7
  29. data/lib/generators/pu/saas/portal_generator.rb +17 -0
  30. data/lib/generators/pu/skills/sync/sync_generator.rb +21 -0
  31. data/lib/plutonium/engine.rb +1 -1
  32. data/lib/plutonium/version.rb +1 -1
  33. data/package.json +1 -1
  34. data/src/css/tokens.css +2 -0
  35. metadata +2 -6
  36. data/.claude/skills/plutonium-connect-resource/SKILL.md +0 -130
  37. data/.claude/skills/plutonium-definition-fields/SKILL.md +0 -535
  38. data/.claude/skills/plutonium-model-features/SKILL.md +0 -286
  39. data/.claude/skills/plutonium-resource/SKILL.md +0 -281
@@ -1,16 +1,29 @@
1
1
  ---
2
2
  name: plutonium-definition
3
- description: Overview of Plutonium resource definitions - structure, inheritance, and best practices
3
+ description: Use when configuring resource definitions - field types, inputs, displays, columns, conditional rendering, nested inputs, or definition structure
4
4
  ---
5
5
 
6
- # Definition Overview
6
+ # Plutonium Resource Definitions
7
7
 
8
- Resource definitions configure **HOW** resources are rendered and interacted with. They are the central configuration point for UI behavior in Plutonium applications.
8
+ **Definitions are generated automatically** - never create them manually:
9
+ - `rails g pu:res:scaffold` creates the base definition
10
+ - `rails g pu:res:conn` creates portal-specific definitions
11
+ - `rails g pu:field:input NAME` creates custom field input components
12
+ - `rails g pu:field:renderer NAME` creates custom field display components
13
+
14
+ Resource definitions configure **HOW** resources are rendered and interacted with. They are the central configuration point for UI behavior.
9
15
 
10
16
  ## Key Principle
11
17
 
12
18
  **All model attributes are auto-detected** - you only declare when overriding defaults.
13
19
 
20
+ Plutonium automatically detects from your model:
21
+ - Database columns (string, text, integer, boolean, datetime, etc.)
22
+ - Associations (belongs_to, has_many, has_one)
23
+ - Active Storage attachments (has_one_attached, has_many_attached)
24
+ - Enums
25
+ - Virtual attributes (with accessor methods)
26
+
14
27
  ## File Location
15
28
 
16
29
  - Main app: `app/definitions/model_name_definition.rb`
@@ -20,7 +33,7 @@ Resource definitions configure **HOW** resources are rendered and interacted wit
20
33
 
21
34
  ```ruby
22
35
  class PostDefinition < Plutonium::Resource::Definition
23
- # Fields, inputs, displays, columns (see definition-fields skill)
36
+ # Fields, inputs, displays, columns
24
37
  field :content, as: :markdown
25
38
  input :title, hint: "Be descriptive"
26
39
  display :content, as: :markdown
@@ -58,23 +71,14 @@ end
58
71
 
59
72
  ### Portal-Specific Overrides
60
73
 
61
- After connecting a resource to a portal, you can create a portal-specific definition to override defaults for that portal only:
62
-
63
74
  ```ruby
64
75
  # packages/admin_portal/app/definitions/admin_portal/post_definition.rb
65
76
  class AdminPortal::PostDefinition < ::PostDefinition
66
- # Override or extend for admin portal only
67
77
  input :internal_notes, as: :text # Only admins see this field
68
78
  scope :pending_review # Admin-specific scope
69
79
  end
70
80
  ```
71
81
 
72
- This lets you:
73
- - Show different fields per portal
74
- - Add portal-specific actions
75
- - Customize search/filters per context
76
- - Keep main app definition clean
77
-
78
82
  ## Separation of Concerns
79
83
 
80
84
  | Layer | Purpose | Example |
@@ -83,56 +87,422 @@ This lets you:
83
87
  | **Policy** | WHAT is visible/editable | `permitted_attributes_for_read` |
84
88
  | **Interaction** | Business logic | `resource.update!(state: :archived)` |
85
89
 
86
- ## Auto-Detection
90
+ ## Core Methods
87
91
 
88
- Plutonium automatically detects from your model:
89
- - Database columns (string, text, integer, boolean, datetime, etc.)
90
- - Associations (belongs_to, has_many, has_one)
91
- - Active Storage/Active Shrine attachments (has_one_attached, has_many_attached)
92
- - Enums
93
- - Virtual attributes (with accessor methods)
94
-
95
- **Only declare fields when you need to override the auto-detected behavior.**
92
+ | Method | Applies To | Use When |
93
+ |--------|-----------|----------|
94
+ | `field` | Forms + Show + Table | Universal type override |
95
+ | `input` | Forms only | Form-specific options |
96
+ | `display` | Show page only | Display-specific options |
97
+ | `column` | Table only | Table-specific options |
96
98
 
97
- ## When to Declare
99
+ ## Basic Usage
98
100
 
99
101
  ```ruby
100
102
  class PostDefinition < ResourceDefinition
101
- # 1. Override auto-detected type
102
- field :content, as: :markdown # text -> rich_text
103
- input :published_at, as: :date # datetime -> date only
103
+ # field - changes type everywhere
104
+ field :content, as: :markdown
104
105
 
105
- # 2. Add custom options
106
- input :title, hint: "Be descriptive", placeholder: "Enter title"
106
+ # input - form-specific
107
+ input :title,
108
+ label: "Article Title",
109
+ hint: "Enter a descriptive title",
110
+ placeholder: "e.g. Getting Started"
111
+
112
+ # display - show page specific
113
+ display :content,
114
+ as: :markdown,
115
+ description: "Published content",
116
+ wrapper: {class: "col-span-full"}
117
+
118
+ # column - table specific
119
+ column :title, label: "Article", align: :center
120
+ column :view_count, align: :end
121
+ end
122
+ ```
107
123
 
108
- # 3. Configure select choices
109
- input :category, as: :select, choices: %w[Tech Business]
124
+ ## Available Field Types
110
125
 
111
- # 4. Add conditional logic
126
+ ### Input Types (Forms)
127
+
128
+ | Category | Types |
129
+ |----------|-------|
130
+ | **Text** | `:string`, `:text`, `:email`, `:url`, `:tel`, `:password` |
131
+ | **Rich Text** | `:markdown` (EasyMDE editor) |
132
+ | **Numeric** | `:number`, `:integer`, `:decimal`, `:range` |
133
+ | **Boolean** | `:boolean` |
134
+ | **Date/Time** | `:date`, `:time`, `:datetime` |
135
+ | **Selection** | `:select`, `:slim_select`, `:radio_buttons`, `:check_boxes` |
136
+ | **Files** | `:file`, `:uppy`, `:attachment` |
137
+ | **Associations** | `:association`, `:secure_association`, `:belongs_to`, `:has_many`, `:has_one` |
138
+ | **Special** | `:hidden`, `:color`, `:phone` |
139
+
140
+ ### Display Types (Show/Index)
141
+
142
+ `:string`, `:text`, `:email`, `:url`, `:phone`, `:markdown`, `:number`, `:integer`, `:decimal`, `:boolean`, `:date`, `:time`, `:datetime`, `:association`, `:attachment`
143
+
144
+ ## Field Options
145
+
146
+ ### Field-Level Options (wrapper)
147
+
148
+ ```ruby
149
+ input :title,
150
+ label: "Custom Label", # Custom label text
151
+ hint: "Help text for forms", # Form help text
152
+ placeholder: "Enter value", # Input placeholder
153
+ description: "For displays" # Display description
154
+ ```
155
+
156
+ ### Tag-Level Options (HTML element)
157
+
158
+ ```ruby
159
+ input :title,
160
+ class: "custom-class", # CSS class
161
+ data: {controller: "custom"}, # Data attributes
162
+ required: true, # HTML required
163
+ readonly: true, # HTML readonly
164
+ disabled: true # HTML disabled
165
+ ```
166
+
167
+ ### Wrapper Options
168
+
169
+ ```ruby
170
+ display :content, wrapper: {class: "col-span-full"}
171
+ input :notes, wrapper: {class: "bg-gray-50"}
172
+ ```
173
+
174
+ ## Select/Choices
175
+
176
+ ### Static Choices
177
+
178
+ ```ruby
179
+ input :category, as: :select, choices: %w[Tech Business Lifestyle]
180
+ input :status, as: :select, choices: Post.statuses.keys
181
+ ```
182
+
183
+ ### Dynamic Choices (requires block)
184
+
185
+ ```ruby
186
+ # Basic dynamic
187
+ input :author do |f|
188
+ choices = User.active.pluck(:name, :id)
189
+ f.select_tag choices: choices
190
+ end
191
+
192
+ # With context access
193
+ input :team_members do |f|
194
+ choices = current_user.organization.users.pluck(:name, :id)
195
+ f.select_tag choices: choices
196
+ end
197
+
198
+ # Based on object state
199
+ input :related_posts do |f|
200
+ choices = if object.persisted?
201
+ Post.where.not(id: object.id).published.pluck(:title, :id)
202
+ else
203
+ []
204
+ end
205
+ f.select_tag choices: choices
206
+ end
207
+ ```
208
+
209
+ ## Conditional Rendering
210
+
211
+ ```ruby
212
+ class PostDefinition < ResourceDefinition
213
+ # Show based on object state
112
214
  display :published_at, condition: -> { object.published? }
215
+ display :rejection_reason, condition: -> { object.rejected? }
113
216
 
114
- # 5. Custom rendering
115
- display :status do |field|
116
- StatusBadgeComponent.new(value: field.value)
217
+ # Show based on environment
218
+ field :debug_info, condition: -> { Rails.env.development? }
219
+ end
220
+ ```
221
+
222
+ **Note:** Use `condition` for UI state logic. Use **policies** for authorization.
223
+
224
+ ## Dynamic Forms (pre_submit)
225
+
226
+ Use `pre_submit: true` to create forms that dynamically show/hide fields based on other field values. When a `pre_submit` field changes, the form re-renders server-side and conditions are re-evaluated.
227
+
228
+ ### Basic Pattern
229
+
230
+ ```ruby
231
+ class PostDefinition < ResourceDefinition
232
+ # Trigger field - causes form to re-render on change
233
+ input :send_notifications, pre_submit: true
234
+
235
+ # Dependent field - only shown when condition is true
236
+ input :notification_channel,
237
+ as: :select,
238
+ choices: %w[Email SMS],
239
+ condition: -> { object.send_notifications? }
240
+ end
241
+ ```
242
+
243
+ ### How It Works
244
+
245
+ 1. User changes a `pre_submit: true` field
246
+ 2. Form submits via Turbo (no page reload)
247
+ 3. Server re-renders the form with updated `object` state
248
+ 4. Fields with `condition` procs are re-evaluated
249
+ 5. Newly visible fields appear, hidden fields disappear
250
+
251
+ ### Multiple Dependent Fields
252
+
253
+ ```ruby
254
+ class QuestionDefinition < ResourceDefinition
255
+ # Primary selector
256
+ input :question_type, as: :select,
257
+ choices: %w[text choice scale date boolean],
258
+ pre_submit: true
259
+
260
+ # Conditional fields based on question_type
261
+ input :max_length,
262
+ as: :integer,
263
+ condition: -> { object.question_type == "text" }
264
+
265
+ input :choices,
266
+ as: :text,
267
+ hint: "One choice per line",
268
+ condition: -> { object.question_type == "choice" }
269
+
270
+ input :min_value,
271
+ as: :integer,
272
+ condition: -> { object.question_type == "scale" }
273
+
274
+ input :max_value,
275
+ as: :integer,
276
+ condition: -> { object.question_type == "scale" }
277
+ end
278
+ ```
279
+
280
+ ### Cascading Dependencies
281
+
282
+ ```ruby
283
+ class PropertyDefinition < ResourceDefinition
284
+ input :property_type, as: :select,
285
+ choices: %w[residential commercial],
286
+ pre_submit: true
287
+
288
+ input :residential_type, as: :select,
289
+ choices: %w[apartment house condo],
290
+ condition: -> { object.property_type == "residential" },
291
+ pre_submit: true
292
+
293
+ input :commercial_type, as: :select,
294
+ choices: %w[office retail warehouse],
295
+ condition: -> { object.property_type == "commercial" },
296
+ pre_submit: true
297
+
298
+ input :apartment_floor,
299
+ as: :integer,
300
+ condition: -> { object.residential_type == "apartment" }
301
+ end
302
+ ```
303
+
304
+ ### Dynamic Choices with pre_submit
305
+
306
+ ```ruby
307
+ class SurveyResponseDefinition < ResourceDefinition
308
+ input :category, as: :select,
309
+ choices: Category.pluck(:name, :id),
310
+ pre_submit: true
311
+
312
+ input :subcategory do |f|
313
+ choices = if object.category.present?
314
+ Category.find(object.category).subcategories.pluck(:name, :id)
315
+ else
316
+ []
317
+ end
318
+ f.select_tag choices: choices
117
319
  end
118
320
  end
119
321
  ```
120
322
 
121
- ## Minimal Definition Example
323
+ ### Tips
324
+
325
+ - Only add `pre_submit: true` to fields that control visibility of other fields
326
+ - Keep dependencies simple - deeply nested conditions are hard to debug
327
+ - The form submits on change, so avoid `pre_submit` on frequently-changed fields
328
+
329
+ ## Custom Rendering
330
+
331
+ ### Block Syntax
332
+
333
+ **For Display (can return any component):**
334
+ ```ruby
335
+ display :status do |field|
336
+ StatusBadgeComponent.new(value: field.value, class: field.dom.css_class)
337
+ end
338
+
339
+ display :metrics do |field|
340
+ if field.value.present?
341
+ MetricsChartComponent.new(data: field.value)
342
+ else
343
+ EmptyStateComponent.new(message: "No metrics")
344
+ end
345
+ end
346
+ ```
347
+
348
+ **For Input (must use form builder methods):**
349
+ ```ruby
350
+ input :birth_date do |f|
351
+ case object.age_category
352
+ when 'adult'
353
+ f.date_tag(min: 18.years.ago.to_date)
354
+ when 'minor'
355
+ f.date_tag(max: 18.years.ago.to_date)
356
+ else
357
+ f.date_tag
358
+ end
359
+ end
360
+ ```
361
+
362
+ ### phlexi_tag (Advanced Display)
363
+
364
+ ```ruby
365
+ # With component class
366
+ display :status, as: :phlexi_tag, with: StatusBadgeComponent
367
+
368
+ # With inline proc
369
+ display :priority, as: :phlexi_tag, with: ->(value, attrs) {
370
+ case value
371
+ when 'high'
372
+ span(class: "badge badge-danger") { "High" }
373
+ when 'medium'
374
+ span(class: "badge badge-warning") { "Medium" }
375
+ else
376
+ span(class: "badge badge-info") { "Low" }
377
+ end
378
+ }
379
+ ```
380
+
381
+ ### Custom Component Class
382
+
383
+ ```ruby
384
+ input :color_picker, as: ColorPickerComponent
385
+ display :chart, as: ChartComponent
386
+ ```
387
+
388
+ ## Column Options
389
+
390
+ ### Alignment
391
+
392
+ ```ruby
393
+ column :title, align: :start # Left (default)
394
+ column :status, align: :center # Center
395
+ column :amount, align: :end # Right
396
+ ```
397
+
398
+ ### Value Formatting
399
+
400
+ ```ruby
401
+ # Truncate long text
402
+ column :description, formatter: ->(value) { value&.truncate(30) }
403
+
404
+ # Format numbers
405
+ column :price, formatter: ->(value) { "$%.2f" % value if value }
406
+
407
+ # Transform values
408
+ column :status, formatter: ->(value) { value&.humanize&.upcase }
409
+ ```
410
+
411
+ **formatter vs block:** Use `formatter` when you only need the value. Use a block when you need the full record:
412
+
413
+ ```ruby
414
+ # formatter - receives just the value
415
+ column :name, formatter: ->(value) { value&.titleize }
416
+
417
+ # block - receives the full record
418
+ column :full_name do |record|
419
+ "#{record.first_name} #{record.last_name}"
420
+ end
421
+ ```
422
+
423
+ ## Nested Inputs
424
+
425
+ Render inline forms for associated records. Requires `accepts_nested_attributes_for` on the model.
426
+
427
+ ### Model Setup
428
+
429
+ ```ruby
430
+ class Post < ResourceRecord
431
+ has_many :comments
432
+ has_one :metadata
433
+
434
+ accepts_nested_attributes_for :comments, allow_destroy: true, limit: 10
435
+ accepts_nested_attributes_for :metadata, update_only: true
436
+ end
437
+ ```
438
+
439
+ ### Basic Declaration
122
440
 
123
441
  ```ruby
124
442
  class PostDefinition < ResourceDefinition
125
- # No field declarations needed - all auto-detected!
443
+ # Block syntax
444
+ nested_input :comments do |n|
445
+ n.input :body, as: :text
446
+ n.input :author_name
447
+ end
126
448
 
127
- # Only customize what you need:
128
- input :content, as: :markdown
129
- display :content, as: :markdown
449
+ # Using another definition
450
+ nested_input :metadata, using: PostMetadataDefinition, fields: %i[seo_title seo_description]
451
+ end
452
+ ```
130
453
 
131
- scope :published
132
- scope :draft
454
+ ### Options
455
+
456
+ | Option | Description |
457
+ |--------|-------------|
458
+ | `limit` | Max records (auto-detected from model, default: 10) |
459
+ | `allow_destroy` | Show delete checkbox (auto-detected from model) |
460
+ | `update_only` | Hide "Add" button, only edit existing |
461
+ | `description` | Help text above the section |
462
+ | `condition` | Proc to show/hide section |
463
+ | `using` | Reference another Definition class |
464
+ | `fields` | Which fields to render from the definition |
465
+
466
+ ```ruby
467
+ nested_input :amenities,
468
+ allow_destroy: true,
469
+ limit: 20,
470
+ description: "Add property amenities" do |n|
471
+ n.input :name
472
+ n.input :icon, as: :select, choices: ICONS
473
+ end
474
+ ```
475
+
476
+ ### Singular Associations
477
+
478
+ For `has_one` and `belongs_to`, limit is automatically 1:
479
+
480
+ ```ruby
481
+ nested_input :profile do |n| # has_one
482
+ n.input :bio
483
+ n.input :website
133
484
  end
134
485
  ```
135
486
 
487
+ ### Gotchas
488
+
489
+ - Model must have `accepts_nested_attributes_for`
490
+ - For custom class names, use `class_name:` in both model and `using:` in definition
491
+ - `update_only: true` hides the Add button
492
+ - Limit is enforced in UI (Add button hidden when reached)
493
+
494
+ ## File Uploads
495
+
496
+ ```ruby
497
+ input :avatar, as: :file
498
+ input :avatar, as: :uppy
499
+
500
+ input :documents, as: :file, multiple: true
501
+ input :documents, as: :uppy,
502
+ allowed_file_types: ['.pdf', '.doc'],
503
+ max_file_size: 5.megabytes
504
+ ```
505
+
136
506
  ## Runtime Customization Hooks
137
507
 
138
508
  Override these methods for dynamic behavior:
@@ -161,15 +531,6 @@ class PostDefinition < ResourceDefinition
161
531
  end
162
532
  ```
163
533
 
164
- ## Context Availability
165
-
166
- | Context | current_user | object | current_parent |
167
- |---------|-------------|--------|----------------|
168
- | Definition file (class level) | No | No | No |
169
- | `condition` procs | Yes | Yes | Yes |
170
- | `input` blocks | Yes | Yes | Yes |
171
- | Page title procs | Yes | Yes (current_record!) | Yes |
172
-
173
534
  ## Form Configuration
174
535
 
175
536
  ```ruby
@@ -182,8 +543,6 @@ class PostDefinition < ResourceDefinition
182
543
  end
183
544
  ```
184
545
 
185
- Singular resources (e.g., `resource :profile` routes or `has_one` nested) auto-hide this button since creating "another" doesn't make sense.
186
-
187
546
  ## Page Customization
188
547
 
189
548
  ```ruby
@@ -216,6 +575,39 @@ class PostDefinition < ResourceDefinition
216
575
  end
217
576
  ```
218
577
 
578
+ ## Context in Blocks
579
+
580
+ Inside `condition` procs and `input` blocks:
581
+ - `object` - The record being edited/displayed
582
+ - `current_user` - The authenticated user
583
+ - `current_parent` - Parent record for nested resources
584
+ - `request`, `params` - Request information
585
+ - All helper methods
586
+
587
+ ## When to Declare
588
+
589
+ ```ruby
590
+ class PostDefinition < ResourceDefinition
591
+ # 1. Override auto-detected type
592
+ field :content, as: :markdown # text -> rich_text
593
+ input :published_at, as: :date # datetime -> date only
594
+
595
+ # 2. Add custom options
596
+ input :title, hint: "Be descriptive", placeholder: "Enter title"
597
+
598
+ # 3. Configure select choices
599
+ input :category, as: :select, choices: %w[Tech Business]
600
+
601
+ # 4. Add conditional logic
602
+ display :published_at, condition: -> { object.published? }
603
+
604
+ # 5. Custom rendering
605
+ display :status do |field|
606
+ StatusBadgeComponent.new(value: field.value)
607
+ end
608
+ end
609
+ ```
610
+
219
611
  ## Best Practices
220
612
 
221
613
  1. **Let auto-detection work** - Don't declare unless overriding
@@ -226,7 +618,7 @@ end
226
618
 
227
619
  ## Related Skills
228
620
 
229
- - `plutonium-definition-fields` - Fields, inputs, displays, columns
230
621
  - `plutonium-definition-actions` - Actions and interactions
231
622
  - `plutonium-definition-query` - Search, filters, scopes, sorting
232
623
  - `plutonium-views` - Custom page, form, display, and table classes
624
+ - `plutonium-forms` - Custom form templates and field builders
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plutonium-definition-actions
3
- description: Add custom actions and interactions to Plutonium resources
3
+ description: Use when adding custom actions, bulk operations, or wiring interactions into Plutonium resource definitions
4
4
  ---
5
5
 
6
6
  # Definition Actions
@@ -418,7 +418,7 @@ end
418
418
  ## Related Skills
419
419
 
420
420
  - `plutonium-definition` - Overview and structure
421
- - `plutonium-definition-fields` - Fields, inputs, displays
421
+ - `plutonium-definition` - Fields, inputs, displays
422
422
  - `plutonium-definition-query` - Search, filters, scopes
423
423
  - `plutonium-interaction` - Writing interaction classes
424
424
  - `plutonium-policy` - Controlling action access
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plutonium-definition-query
3
- description: Configure search, filters, scopes, and sorting for Plutonium resources
3
+ description: Use when adding search, filters, named scopes, or sorting to a Plutonium resource definition
4
4
  ---
5
5
 
6
6
  # Definition Query
@@ -360,5 +360,5 @@ end
360
360
  ## Related Skills
361
361
 
362
362
  - `plutonium-definition` - Overview and structure
363
- - `plutonium-definition-fields` - Fields, inputs, displays
363
+ - `plutonium-definition` - Fields, inputs, displays
364
364
  - `plutonium-definition-actions` - Actions and interactions
@@ -1,10 +1,14 @@
1
1
  ---
2
2
  name: plutonium-forms
3
- description: Plutonium forms - custom templates, Phlex form components, field builders, and theming
3
+ description: Use when building custom form templates, overriding field builders, or theming form components in Plutonium
4
4
  ---
5
5
 
6
6
  # Plutonium Forms
7
7
 
8
+ **Use generators for custom field types:**
9
+ - `rails g pu:field:input NAME` creates a custom form input component
10
+ - `rails g pu:field:renderer NAME` creates a custom display renderer
11
+
8
12
  Plutonium forms are built on [Phlexi::Form](https://github.com/radioactive-labs/phlexi-form), providing a Ruby-first approach to form building with Phlex components.
9
13
 
10
14
  ## Form Class Hierarchy
@@ -447,7 +451,7 @@ end
447
451
 
448
452
  ## Related Skills
449
453
 
450
- - `plutonium-definition-fields` - Input configuration (as:, hint:, condition:)
454
+ - `plutonium-definition` - Input configuration (as:, hint:, condition:)
451
455
  - `plutonium-views` - Custom page classes
452
456
  - `plutonium-assets` - TailwindCSS and component theming
453
457
  - `plutonium-interaction` - Interactive action forms
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plutonium-installation
3
- description: Installing Plutonium in a Rails application - setup, generators, and configuration
3
+ description: Use when installing Plutonium in a new or existing Rails app - generators, configuration, and initial setup
4
4
  ---
5
5
 
6
6
  # Plutonium Installation
@@ -292,11 +292,11 @@ For models that already exist in your app:
292
292
 
293
293
  ## Related Skills
294
294
 
295
- - `plutonium-resource` - Resource architecture overview
295
+ - `plutonium` - Resource architecture overview
296
296
  - `plutonium-rodauth` - Authentication setup and configuration
297
297
  - `plutonium-package` - Feature and portal packages
298
298
  - `plutonium-portal` - Portal configuration
299
299
  - `plutonium-views` - Custom pages, layouts, and Phlex components
300
300
  - `plutonium-assets` - TailwindCSS and custom styling
301
301
  - `plutonium-create-resource` - Resource scaffold options
302
- - `plutonium-connect-resource` - Portal connection
302
+ - `plutonium-portal` - Portal connection
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plutonium-interaction
3
- description: Plutonium interactions - encapsulated business logic for custom actions
3
+ description: Use when writing interaction classes for custom business logic, multi-step operations, or actions beyond basic CRUD
4
4
  ---
5
5
 
6
6
  # Plutonium Interactions
@@ -68,7 +68,7 @@ input :content, as: :text
68
68
  input :date, as: :date
69
69
  ```
70
70
 
71
- See `plutonium-definition-fields` skill for all input types and options.
71
+ See `plutonium-definition` skill for all input types and options.
72
72
 
73
73
  ## Presentation
74
74
 
@@ -380,4 +380,4 @@ end
380
380
  - `plutonium-definition-actions` - Declaring actions in definitions
381
381
  - `plutonium-forms` - Custom interaction form templates
382
382
  - `plutonium-policy` - Controlling access to actions
383
- - `plutonium-resource` - How interactions fit in the architecture
383
+ - `plutonium` - How interactions fit in the architecture
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plutonium-invites
3
- description: Plutonium user invites - invitation system for multi-tenant apps with entity memberships
3
+ description: Use when setting up user invitations with entity membership in a multi-tenant Plutonium app
4
4
  ---
5
5
 
6
6
  # Plutonium User Invites