renders as:
+
+
+ SCSS File Pairing:
+ Each action/layout can have a companion SCSS file with all styles
+ scoped to the component class:
+
+ // rsx/app/frontend/contacts/contacts_index_action.scss
+ .Contacts_Index_Action {
+ .filters { margin-bottom: 1rem; }
+ .contact-list { ... }
+ }
+
+ // rsx/app/frontend/frontend_layout.scss
+ .Frontend_Layout {
+ .app-sidebar { width: 250px; }
+ .app-content { margin-left: 250px; }
+ }
+
+ Enforcement:
+ SCSS files in rsx/app/ must wrap all rules in a single class
+ matching the action/layout name. This is enforced by the manifest
+ scanner and prevents CSS conflicts between pages.
+
+ See scss man page for complete scoping rules and philosophy.
+
URL GENERATION
CRITICAL: All URLs must use Rsx::Route() or Rsx.Route(). Raw URLs like
"/contacts" will produce errors.
@@ -833,3 +868,4 @@ SEE ALSO
routing(3) - URL generation and route patterns
modals(3) - Modal dialogs in SPA context
ajax_error_handling(3) - Error handling patterns
+ scss(3) - SCSS scoping conventions and component-first philosophy
diff --git a/docs/CLAUDE.dist.md b/docs/CLAUDE.dist.md
index 4556c9828..13cb1d7f0 100644
--- a/docs/CLAUDE.dist.md
+++ b/docs/CLAUDE.dist.md
@@ -430,19 +430,21 @@ The process involves creating Action classes with @route decorators and converti
**NO inline styles, scripts, or event handlers** - Use companion `.scss` and `.js` files.
**jqhtml components** work fully in Blade (no slots).
-### SCSS Pairing
+### SCSS Component-First Architecture
-For page/component-specific styles, wrap all rules in a class matching the component name:
+**Philosophy**: Every styled element is a component. If it needs custom styles, give it a name, a jqhtml definition, and scoped SCSS. This eliminates CSS spaghetti - generic classes overriding each other unpredictably across files.
-```scss
-/* my_component.scss - Scoped to component */
-.My_Component { /* Matches component class or @rsx_id */
- .content { padding: 20px; }
- /* All component-specific rules here */
-}
-```
+**Recognition**: When building a page, ask: "Is this structure unique, or a pattern?" A datagrid page with toolbar, tabs, filters, and search is a *pattern* - create `Datagrid_Card` once with slots, use it everywhere. A one-off project dashboard is *unique* - create `Project_Dashboard` for that page. If you're about to copy-paste structural markup, stop and extract a component.
-**Convention**: Each Blade view, jqhtml action, or component automatically gets its name as a class on its root element, enabling scoped styling.
+**Composition**: Use slots to separate structure from content. The component owns layout and styling; pages provide the variable parts via slots. This keeps pages declarative and components reusable.
+
+**Enforcement**: SCSS in `rsx/app/` and `rsx/theme/components/` must wrap in a single component class matching the jqhtml/blade file. This works because all jqhtml components, SPA actions/layouts, and Blade views with `@rsx_id` automatically render with `class="Component_Name"` on their root element. `rsx/lib/` is for non-visual plumbing (validators, utilities). `rsx/theme/` (outside components/) holds primitives, variables, Bootstrap overrides.
+
+**Variables**: Define shared values (colors, spacing, border-radius) in `rsx/theme/variables.scss` or similar. These must be explicitly included before directory includes in bundle definitions. Component-local variables can be defined within the scoped rule.
+
+**Supplemental files**: Multiple SCSS files can target the same component (e.g., breakpoint-specific styles) if a primary file with matching filename exists.
+
+Details: `php artisan rsx:man scss`
### JavaScript for Blade Pages