Files
pictureFrame/.claude/skills/oro-frontend-dev/SKILL.md
T
football2801 a536baabd6 feat: initial commit — BMAD tooling, Claude memories, firmware scaffold
Adds the complete project foundation:
- BMAD BMM workflow tooling (_bmad/)
- Claude slash commands, skills, and project memories (.claude/)
- ESP32 firmware scaffold (PlatformIO + Waveshare e-ink driver)
- .gitignore excluding _bmad-output/ and .pio/ build artifacts

Planning artifacts (PRD, architecture, epics) are intentionally not
tracked — they live in _bmad-output/ per project convention.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 15:38:46 -04:00

11 KiB

name, description
name description
oro-frontend-dev OroCommerce frontend development reference covering storefront themes, back-office themes, layouts, SCSS, JavaScript architecture (Chaplin/Backbone), page components, templates, and asset management. Use when customizing the storefront UI, modifying admin templates, writing JS components, or styling OroCommerce pages.

OroCommerce Frontend Developer

Reference for frontend/UI development on OroCommerce. Full docs: https://doc.oroinc.com/frontend/

Two Theme Systems

OroCommerce has two separate theme architectures:

Area Framework Templates JS Docs
Storefront OroLayouts (SEO-friendly, no SPA) Layout YAML + Twig blocks Chaplin/Backbone https://doc.oroinc.com/frontend/storefront/
Back-office Placeholders (SPA-like, Twig+Underscore) Twig extends @OroUI Chaplin/Backbone https://doc.oroinc.com/frontend/back-office/

Themes are NOT interchangeable between storefront and back-office.

Storefront Theming

Theme Structure

Resources/views/layouts/{theme_name}/
    theme.yml              # theme definition (label, parent, icon)
    config/
        assets.yml         # SCSS entry points
        jsmodules.yml      # JS module registration
        datagrids.yml      # frontend datagrid configs
    templates/             # Twig block templates
    page/                  # per-page layout overrides

theme.yml

Basic:

label: 'My Custom Theme'
parent: default
icon: bundles/mybundle/images/theme-icon.png
groups: [commerce]
rtl_support: true

Full configuration with admin-selectable options:

label: 'Acme Theme'
parent: default
groups: [commerce]
rtl_support: true

configuration:
  sections:
    header:
      label: Header
      options:
        promotional_content:
          label: oro_frontend.theme.default.configuration.header.promotional_content.label
          type: content_block_selector
          options:
            required: false
        standalone_main_menu:
          label: oro_frontend.theme.default.configuration.header.standalone_main_menu.label
          type: checkbox
          default: checked
          previews:
            checked: 'bundles/orofrontend/images/previews/menu-standalone.png'
            unchecked: 'bundles/orofrontend/images/previews/menu-hamburger.png'
    product_listing:
      label: 'oro.product.theme.default.configuration.product_listing.label'
      options:
        filters_position:
          label: 'oro.product.theme.default.configuration.product_listing.filters_position.label'
          type: radio
          default: sidebar
          values:
            top: 'oro.product.theme.default.configuration.product_listing.filters_position.values.top'
            sidebar: 'oro.product.theme.default.configuration.product_listing.filters_position.values.sidebar'

Configuration option types: content_block_selector, menu_selector, checkbox, radio, select.

Layout Updates

Layout updates are YAML files that modify page structure:

layout:
    actions:
        - '@setBlockTheme':
            id: page_container
            themes: '@MyBundle/layouts/my_theme/page/layout.html.twig'
        - '@add':
            id: my_custom_block
            parentId: page_content
            blockType: text
            options:
                text: '=data["locale"].getLanguage()'
        - '@remove':
            id: unwanted_block
        - '@move':
            id: existing_block
            parentId: new_parent

Place layout updates in route-specific directories to target individual pages:

Resources/views/layouts/{theme}/
    layout.yml                                    # global layout (all pages)
    oro_frontend_root/frontend_root.yml           # homepage
    oro_product_frontend_product_index/product_index.yml  # PLP
    oro_product_frontend_product_view/product_view.yml    # PDP
    oro_checkout_frontend_checkout/checkout.yml    # checkout

Block Types

blockType Purpose
container Wraps child blocks with a div
text Static text or expression
block Custom Twig-rendered block
content_block References admin-managed content block by alias
menu Renders a navigation menu

Layout Data Expressions

Access data providers and context variables in YAML options:

options:
  vars:
    # Data provider methods (registered via layout_data_provider tag)
    topCategories: '=data["category_provider"].getRootCategoriesWithSlugs()'
    featuredCount: '=data["product_provider"].getFeaturedProductCount()'
    ctaLinks: '=data["cta_link_provider"].getLinks(data["menu"].getMenu("commerce_main_menu"))'

    # Context variables (route params, request attributes)
    category: '=data["category_provider"].getCategoryById(context["category_id"])'

@addTree Action

Add multiple blocks at once:

- '@addTree':
    items:
      footer_menu:
        blockType: menu
        options:
          item: '=data["menu"].getMenu("commerce_footer_links")'
          depth: 2
    tree:
      page_footer_base:
        footer_menu: ~

@setBlockTheme with Multiple Files

- '@setBlockTheme':
    themes:
      - 'templates/layout.html.twig'
      - 'templates/page-footer/footer_branding.html.twig'
      - 'templates/navigation/sidebar_menu.html.twig'

Twig Block Naming Convention

Block names in layout Twig templates follow: _{blockId}_widget

{% block _my_custom_block_widget %}
    <div {{ block('block_attributes') }}>
        {{ block_widget(block) }}
    </div>
{% endblock %}

SCSS / Stylesheets

Register SCSS in config/assets.yml:

styles:
  inputs:
    - 'bundles/acmetheme/scss/styles.scss'
  output: 'css/styles.css'

Recommended SCSS directory organization:

scss/
    styles.scss           # main entry point (@import all)
    variables/
        _colors.scss      # color palette as Sass maps
        _typography.scss
        _mixins.scss
    components/
        _product-cards.scss
        _buttons.scss
    layout/
        _page-header.scss
        _page-footer.scss
        _product-view.scss
        _product-index.scss
        _checkout.scss
    navigation/
        _sidebar.scss
        _topbar.scss

Color palette using Sass maps (Oro pattern):

@use 'sass:map';

$theme-color-palette: (
    'brand': (
        'primary': #424242,
        'secondary': #A89571,
    ),
    'semantic': (
        'success': #005E1F,
        'error': #D32F2F,
    )
) !default;

$color-palette: map.deep-merge($color-palette, $theme-color-palette);

Access via get-var-color('brand', 'primary'). Build: php bin/console oro:assets:build.

SVG Icons

Custom icons go in the theme's icons directory. Register via theme config.

Back-Office Theming

Twig Template Overrides

Override admin templates by mirroring directory structure under Resources/views/.

Common base templates to extend:

  • @OroUI/actions/index.html.twig -- list/grid pages
  • @OroUI/actions/view.html.twig -- detail/view pages
  • @OroUI/actions/update.html.twig -- create/edit form pages

Use Oro UI macros for consistent rendering:

{% import '@OroUI/macros.html.twig' as UI %}
{{ UI.renderProperty('Label', value) }}
{{ UI.renderHtmlProperty('HTML Label', htmlValue) }}

Placeholders

Inject content into predefined back-office page regions.

# Resources/config/oro/placeholders.yml
placeholders:
    oro_view_additional_data:
        items:
            my_custom_section:
                order: 50
                template: '@AcmeExample/Placeholder/section.html.twig'
                applicable: '@acme.placeholder_filter->isApplicable'

Common placeholder targets:

  • oro_view_additional_data -- entity view page extra sections
  • oro_widget_side_bar -- sidebar widgets
  • oro_title_before / oro_title_after -- title area

Conditional rendering via applicable filter (service method returning bool). Placeholders are back-office only; use Layout Updates for storefront.

SCSS

Override admin SCSS variables or add new stylesheets via theme settings.

JavaScript Architecture

Built on Chaplin.js (extends Backbone.js). Key concepts:

Page Components

The primary extension mechanism. Define in HTML via data attributes:

<div data-page-component-module="mybundle/js/app/components/my-component"
     data-page-component-options="{{ options|json_encode }}">
</div>

Component lifecycle: created on page:update, disposed on page change.

JS Module Registration

Register modules in Resources/config/jsmodules.yml:

dynamic-imports:
    mybundle:
        - mybundle/js/app/components/my-component

aliases:
    jquery$: oroui/js/extend/jquery

# Override an existing module with custom implementation
map:
  '*':
    'orofrontend/js/app/datafilter/frontend-multiselect-decorator': 'acmetheme/js/custom-multiselect-decorator'

App Modules

Execute code at application startup (auto-initialized on every page):

app-modules:
    - acmetheme/js/app/modules/inventory-checker
    - acmetheme/js/app/modules/checkout-shipping-options

AMD Module Pattern

Oro's JS uses AMD define() with the oroui/js/mediator for cross-component communication:

define(function(require) {
    'use strict';

    const mediator = require('oroui/js/mediator');
    const $ = require('jquery');

    class MyComponent {
        constructor() {
            $(document).ready(() => {
                mediator.on('checkout:shipping-method:rendered', this.onShippingRendered);
            });
        }

        onShippingRendered() {
            // DOM manipulation after Oro renders shipping methods
        }
    }

    new MyComponent();
    return MyComponent;
});

Key mediator events: checkout:shipping-method:rendered, filters-manager:after-applying-state, page:update, page:afterChange.

Page Events

System events during page lifecycle:

  1. page:beforeChange
  2. page:request
  3. page:update -- content is updated, init components
  4. page:afterChange -- all components initialized

File Naming Convention

js/app/
    components/       # PageComponent implementations
    controllers/      # Chaplin controllers (rare -- PageController handles all)
    models/           # Backbone models and collections
    views/            # Backbone views
    modules/          # App modules (startup code)
templates/            # Underscore.js templates (*.html)

Asset Build

php bin/console oro:assets:build          # build all themes
php bin/console oro:assets:build --watch   # watch mode for dev
php bin/console assets:install            # symlink public assets

Requires Node.js >= 22 and NPM > 10.

RTL Support

Enable Right-to-Left UI via theme configuration. See: https://doc.oroinc.com/frontend/rtl-support/

Additional Resources