refactor: split architecture rules into domain-specific files
Split the monolithic .architecture-rules.yaml (1700+ lines) into focused domain-specific files in .architecture-rules/ directory: - _main.yaml: Core config, principles, ignore patterns, severity levels - api.yaml: API endpoint rules (API-001 to API-005) - service.yaml: Service layer rules (SVC-001 to SVC-007) - model.yaml: Model rules (MDL-001 to MDL-004) - exception.yaml: Exception handling rules (EXC-001 to EXC-005) - naming.yaml: Naming convention rules (NAM-001 to NAM-005) - auth.yaml: Auth and multi-tenancy rules (AUTH-*, MT-*) - middleware.yaml: Middleware rules (MDW-001 to MDW-002) - frontend.yaml: Frontend rules (JS-*, TPL-*, FE-*, CSS-*) - language.yaml: Language/i18n rules (LANG-001 to LANG-010) - quality.yaml: Code quality rules (QUAL-001 to QUAL-003) Also creates scripts/validators/ module with base classes for future modular validator extraction. The validate_architecture.py loader now auto-detects and merges split YAML files while maintaining backward compatibility with single file mode. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
539
.architecture-rules/frontend.yaml
Normal file
539
.architecture-rules/frontend.yaml
Normal file
@@ -0,0 +1,539 @@
|
||||
# Architecture Rules - Frontend Rules
|
||||
# Combined rules for JavaScript, Templates, Components, and Styling
|
||||
|
||||
# ============================================================================
|
||||
# JAVASCRIPT ARCHITECTURE RULES
|
||||
# ============================================================================
|
||||
|
||||
javascript_rules:
|
||||
|
||||
- id: "JS-001"
|
||||
name: "Use centralized logger, not console"
|
||||
severity: "error"
|
||||
description: |
|
||||
Use window.LogConfig.createLogger() for consistent logging.
|
||||
Never use console.log, console.error, console.warn directly.
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
anti_patterns:
|
||||
- "console\\.log"
|
||||
- "console\\.error"
|
||||
- "console\\.warn"
|
||||
exceptions:
|
||||
- "// eslint-disable"
|
||||
- "console.log('✅"
|
||||
auto_exclude_files:
|
||||
- "init-*.js"
|
||||
|
||||
- id: "JS-002"
|
||||
name: "Use lowercase apiClient for API calls"
|
||||
severity: "error"
|
||||
description: |
|
||||
Use lowercase 'apiClient' consistently, not 'ApiClient' or 'API_CLIENT'
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
anti_patterns:
|
||||
- "ApiClient\\."
|
||||
- "API_CLIENT\\."
|
||||
required_pattern: "apiClient\\."
|
||||
|
||||
- id: "JS-003"
|
||||
name: "Alpine components must spread ...data()"
|
||||
severity: "error"
|
||||
description: |
|
||||
All Alpine.js components must inherit base layout data using spread operator
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
required_in_alpine_components:
|
||||
- "\\.\\.\\.data\\(\\)"
|
||||
|
||||
- id: "JS-004"
|
||||
name: "Alpine components must set currentPage"
|
||||
severity: "error"
|
||||
description: |
|
||||
All Alpine.js page components must set a currentPage identifier
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
required_in_alpine_components:
|
||||
- "currentPage:"
|
||||
|
||||
- id: "JS-005"
|
||||
name: "Initialization methods must include guard"
|
||||
severity: "error"
|
||||
description: |
|
||||
Init methods should prevent duplicate initialization with guard
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
recommended_pattern: |
|
||||
if (window._pageInitialized) return;
|
||||
window._pageInitialized = true;
|
||||
|
||||
- id: "JS-006"
|
||||
name: "All async operations must have try/catch with error logging"
|
||||
severity: "error"
|
||||
description: |
|
||||
All API calls and async operations must have error handling
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
check: "async_error_handling"
|
||||
|
||||
- id: "JS-007"
|
||||
name: "Set loading state before async operations"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Loading state should be set before and cleared after async operations
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
recommended_pattern: |
|
||||
loading = true;
|
||||
try {
|
||||
// operation
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
|
||||
- id: "JS-008"
|
||||
name: "Use apiClient for API calls, not raw fetch()"
|
||||
severity: "error"
|
||||
description: |
|
||||
All API calls must use the apiClient helper instead of raw fetch().
|
||||
The apiClient automatically:
|
||||
- Adds Authorization header with JWT token from cookies
|
||||
- Sets Content-Type headers
|
||||
- Handles error responses consistently
|
||||
- Provides logging integration
|
||||
|
||||
WRONG (raw fetch):
|
||||
const response = await fetch('/api/v1/admin/products/123');
|
||||
|
||||
RIGHT (apiClient):
|
||||
const response = await apiClient.get('/admin/products/123');
|
||||
const result = await apiClient.post('/admin/products', data);
|
||||
await apiClient.delete('/admin/products/123');
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
anti_patterns:
|
||||
- "fetch\\('/api/"
|
||||
- 'fetch\\("/api/'
|
||||
- "fetch\\(`/api/"
|
||||
exceptions:
|
||||
- "init-api-client.js"
|
||||
|
||||
- id: "JS-009"
|
||||
name: "Use Utils.showToast() for notifications, not alert() or window.showToast"
|
||||
severity: "error"
|
||||
description: |
|
||||
All user notifications must use Utils.showToast() from static/shared/js/utils.js.
|
||||
Never use browser alert() dialogs or undefined window.showToast.
|
||||
|
||||
Utils.showToast() provides:
|
||||
- Consistent styling (Tailwind-based toast in bottom-right corner)
|
||||
- Automatic fade-out after duration
|
||||
- Color-coded types (success=green, error=red, warning=yellow, info=blue)
|
||||
|
||||
WRONG (browser dialog):
|
||||
alert('Product saved successfully');
|
||||
|
||||
RIGHT (Utils helper):
|
||||
Utils.showToast('Product saved successfully', 'success');
|
||||
Utils.showToast('Failed to save product', 'error');
|
||||
pattern:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
anti_patterns:
|
||||
- "alert\\("
|
||||
- "window\\.showToast"
|
||||
exceptions:
|
||||
- "utils.js"
|
||||
|
||||
# ============================================================================
|
||||
# TEMPLATE RULES (Jinja2)
|
||||
# ============================================================================
|
||||
|
||||
template_rules:
|
||||
|
||||
- id: "TPL-001"
|
||||
name: "Admin templates must extend admin/base.html"
|
||||
severity: "error"
|
||||
description: |
|
||||
All admin templates must extend the base template for consistency.
|
||||
|
||||
Auto-excluded files:
|
||||
- login.html - Standalone login page (no sidebar/navigation)
|
||||
- errors/*.html - Error pages extend errors/base.html instead
|
||||
- test-*.html - Test/development templates
|
||||
|
||||
Standalone template markers (place in first 5 lines):
|
||||
- {# standalone #} - Mark template as intentionally standalone
|
||||
- {# noqa: TPL-001 #} - Standard noqa style to suppress error
|
||||
- <!-- standalone --> - HTML comment style
|
||||
pattern:
|
||||
file_pattern: "app/templates/admin/**/*.html"
|
||||
required_patterns:
|
||||
- "{% extends ['\"]admin/base\\.html['\"] %}"
|
||||
auto_exclude_files:
|
||||
- "login.html"
|
||||
- "errors/"
|
||||
- "test-"
|
||||
standalone_markers:
|
||||
- "{# standalone #}"
|
||||
- "{# noqa: tpl-001 #}"
|
||||
- "<!-- standalone -->"
|
||||
exceptions:
|
||||
- "base.html"
|
||||
- "partials/"
|
||||
|
||||
- id: "TPL-002"
|
||||
name: "Vendor templates must extend vendor/base.html"
|
||||
severity: "error"
|
||||
description: "All vendor templates must extend the base template"
|
||||
pattern:
|
||||
file_pattern: "app/templates/vendor/**/*.html"
|
||||
required_patterns:
|
||||
- "{% extends ['\"]vendor/base\\.html['\"] %}"
|
||||
exceptions:
|
||||
- "base.html"
|
||||
- "partials/"
|
||||
|
||||
- id: "TPL-003"
|
||||
name: "Shop templates must extend shop/base.html"
|
||||
severity: "error"
|
||||
description: "All shop templates must extend the base template"
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
required_patterns:
|
||||
- "{% extends ['\"]shop/base\\.html['\"] %}"
|
||||
exceptions:
|
||||
- "base.html"
|
||||
- "partials/"
|
||||
|
||||
- id: "TPL-004"
|
||||
name: "Use x-text for dynamic text content (prevents XSS)"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Use x-text directive for dynamic content to prevent XSS vulnerabilities
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
recommended_pattern: '<p x-text="item.name"></p>'
|
||||
|
||||
- id: "TPL-005"
|
||||
name: "Use x-html ONLY for safe content"
|
||||
severity: "error"
|
||||
description: |
|
||||
Use x-html only for trusted content like icons, never for user-generated content
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
safe_usage:
|
||||
- 'x-html="\\$icon\\('
|
||||
|
||||
- id: "TPL-006"
|
||||
name: "Implement loading state for data loads"
|
||||
severity: "warning"
|
||||
description: |
|
||||
All templates that load data should show loading state
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
recommended_pattern: '<div x-show="loading">Loading...</div>'
|
||||
|
||||
- id: "TPL-007"
|
||||
name: "Implement empty state when no data"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Show empty state when lists have no items
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
recommended_pattern: '<template x-if="items.length === 0">No items</template>'
|
||||
|
||||
# ============================================================================
|
||||
# FRONTEND COMPONENT RULES
|
||||
# ============================================================================
|
||||
|
||||
frontend_component_rules:
|
||||
|
||||
- id: "FE-001"
|
||||
name: "Use pagination macro instead of inline HTML"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Use the shared pagination macro instead of duplicating pagination HTML.
|
||||
Import from shared/macros/pagination.html.
|
||||
|
||||
RIGHT (use macro):
|
||||
{% from 'shared/macros/pagination.html' import pagination %}
|
||||
{{ pagination() }}
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
anti_patterns:
|
||||
- 'aria-label="Table navigation"'
|
||||
- "previousPage\\(\\).*nextPage\\(\\)"
|
||||
exceptions:
|
||||
- "shared/macros/pagination.html"
|
||||
- "components.html"
|
||||
|
||||
- id: "FE-002"
|
||||
name: "Use $icon() helper instead of inline SVGs"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Use the Alpine.js $icon() helper for consistent iconography.
|
||||
Do not use inline <svg> elements.
|
||||
|
||||
RIGHT (icon helper):
|
||||
<span x-html="$icon('arrow-left', 'w-4 h-4')"></span>
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
anti_patterns:
|
||||
- "<svg.*viewBox.*>.*</svg>"
|
||||
exceptions:
|
||||
- "base.html"
|
||||
- "components.html"
|
||||
- "shared/macros/"
|
||||
|
||||
- id: "FE-003"
|
||||
name: "Use table macros for consistent table styling"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared table macros for consistent table styling.
|
||||
Import from shared/macros/tables.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/tables.html' import"
|
||||
|
||||
- id: "FE-004"
|
||||
name: "Use form macros for consistent form styling"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared form macros for consistent input styling and validation.
|
||||
Import from shared/macros/forms.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/forms.html' import"
|
||||
|
||||
- id: "FE-008"
|
||||
name: "Use number_stepper macro for quantity inputs"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Use the shared number_stepper macro instead of raw <input type="number">.
|
||||
This ensures consistent styling, proper dark mode support, and hides
|
||||
native browser spinners that render inconsistently.
|
||||
|
||||
RIGHT (use macro):
|
||||
{% from 'shared/macros/inputs.html' import number_stepper %}
|
||||
{{ number_stepper(model='quantity', min=1, max=99) }}
|
||||
|
||||
Suppress with:
|
||||
- {# noqa: FE-008 #} on the line or at file level
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
anti_patterns:
|
||||
- 'type="number"'
|
||||
- "type='number'"
|
||||
exceptions:
|
||||
- "shared/macros/inputs.html"
|
||||
- "components.html"
|
||||
|
||||
- id: "FE-009"
|
||||
name: "Use product_card macro for product displays"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared product_card macro for consistent product presentation.
|
||||
Import from shared/macros/shop/product-card.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/product-card.html' import"
|
||||
|
||||
- id: "FE-010"
|
||||
name: "Use product_grid macro for product listings"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared product_grid macro for responsive product grids.
|
||||
Import from shared/macros/shop/product-grid.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/product-grid.html' import"
|
||||
|
||||
- id: "FE-011"
|
||||
name: "Use add_to_cart macros for cart interactions"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared add-to-cart macros for consistent cart functionality.
|
||||
Import from shared/macros/shop/add-to-cart.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/add-to-cart.html' import"
|
||||
|
||||
- id: "FE-012"
|
||||
name: "Use mini_cart macro for cart dropdown"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared mini_cart macros for header cart functionality.
|
||||
Import from shared/macros/shop/mini-cart.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/mini-cart.html' import"
|
||||
|
||||
- id: "FE-013"
|
||||
name: "Use product_gallery macro for image galleries"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared product_gallery macros for product image displays.
|
||||
Import from shared/macros/shop/product-gallery.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/product-gallery.html' import"
|
||||
|
||||
- id: "FE-014"
|
||||
name: "Use variant_selector macros for product options"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared variant_selector macros for product variant selection.
|
||||
Import from shared/macros/shop/variant-selector.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/variant-selector.html' import"
|
||||
|
||||
- id: "FE-015"
|
||||
name: "Use product_info macros for product details"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared product_info macros for product detail sections.
|
||||
Import from shared/macros/shop/product-info.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/product-info.html' import"
|
||||
|
||||
- id: "FE-016"
|
||||
name: "Use product_tabs macro for product content tabs"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared product_tabs macros for tabbed product information.
|
||||
Import from shared/macros/shop/product-tabs.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/product-tabs.html' import"
|
||||
|
||||
- id: "FE-017"
|
||||
name: "Use category_nav macros for category navigation"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared category_nav macros for category navigation sidebars and menus.
|
||||
Import from shared/macros/shop/category-nav.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/category-nav.html' import"
|
||||
|
||||
- id: "FE-018"
|
||||
name: "Use breadcrumbs macros for breadcrumb navigation"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared breadcrumbs macros for navigation trails.
|
||||
Import from shared/macros/shop/breadcrumbs.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/breadcrumbs.html' import"
|
||||
|
||||
- id: "FE-019"
|
||||
name: "Use search_bar macros for product search"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared search_bar macros for product search functionality.
|
||||
Import from shared/macros/shop/search-bar.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/search-bar.html' import"
|
||||
|
||||
- id: "FE-020"
|
||||
name: "Use filter_sidebar macros for product filtering"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared filter_sidebar macros for product filtering panels.
|
||||
Import from shared/macros/shop/filter-sidebar.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/filter-sidebar.html' import"
|
||||
|
||||
- id: "FE-021"
|
||||
name: "Use star_rating macros for rating displays"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared star_rating macros for all rating displays and inputs.
|
||||
Import from shared/macros/shop/star-rating.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/star-rating.html' import"
|
||||
|
||||
- id: "FE-022"
|
||||
name: "Use review macros for review displays"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared review macros for product reviews.
|
||||
Import from shared/macros/shop/reviews.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/reviews.html' import"
|
||||
|
||||
- id: "FE-023"
|
||||
name: "Use trust_badges macros for trust signals"
|
||||
severity: "info"
|
||||
description: |
|
||||
Use the shared trust_badges macros for security and trust indicators.
|
||||
Import from shared/macros/shop/trust-badges.html.
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
encouraged_patterns:
|
||||
- "{% from 'shared/macros/shop/trust-badges.html' import"
|
||||
|
||||
# ============================================================================
|
||||
# FRONTEND STYLING RULES
|
||||
# ============================================================================
|
||||
|
||||
styling_rules:
|
||||
|
||||
- id: "CSS-001"
|
||||
name: "Use Tailwind utility classes"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Prefer Tailwind utility classes over custom CSS
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
encouraged: true
|
||||
|
||||
- id: "CSS-002"
|
||||
name: "Support dark mode with dark: prefix"
|
||||
severity: "warning"
|
||||
description: |
|
||||
All color classes should include dark mode variants
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
recommended_pattern: 'class="bg-white dark:bg-gray-800"'
|
||||
|
||||
- id: "CSS-003"
|
||||
name: "Shop templates use vendor theme CSS variables"
|
||||
severity: "error"
|
||||
description: |
|
||||
Shop templates must use CSS variables for vendor-specific theming
|
||||
pattern:
|
||||
file_pattern: "app/templates/shop/**/*.html"
|
||||
required_pattern: 'var\\(--color-primary\\)'
|
||||
|
||||
- id: "CSS-004"
|
||||
name: "Mobile-first responsive design"
|
||||
severity: "warning"
|
||||
description: |
|
||||
Use mobile-first responsive classes
|
||||
pattern:
|
||||
file_pattern: "app/templates/**/*.html"
|
||||
recommended_pattern: 'class="grid-cols-1 md:grid-cols-2 lg:grid-cols-4"'
|
||||
Reference in New Issue
Block a user