Saltar a contenido

ADR 027: Template runtime por skin

Estado

Aceptado — 2026-07

Relacionado con ADR 026, ADR 003, ADR 012.

Contexto

Los widgets del panel eran componentes React monolíticos en @cortex/panel-shadcn. Cambiar la presentación por theme exigía recompilar el bundle npm, equivalente a editar el módulo PHP en lugar del .phtml del theme en Magento.

Decisión

Separar controller (headless) de template (view por skin):

Capa Magento HIVE
Block (lógica) Hook/controller en @cortex/panel-core (useDataTableController, useFormWidgetController, useStatCardController)
.phtml (markup theme) View React en skin (*View.base.tsx) cargada en runtime vía SkinTemplateLoader
CSS theme skins/{skin}.css bajo [data-skin]
pub/static public/skins/{skin}/assets/

Contrato controller

  • Vive en packages/cortex-panel-core/src/widgets/{widget}/.
  • Sin JSX; usa usePanel() para datos y acciones.
  • Tests unitarios en panel-core (vitest).

Contrato template

  • Vive en packages/cortex-panel-shadcn/src/widgets/{widget}/*View.base.tsx (fase 2).
  • En runtime, skin publica public/skins/{skin}/templates/registry.js con registerSkinTemplates(registry) (fase 3).
  • WidgetRegistry.resolve(type, skin, template) elige la view activa.

Skin manifest

skinManifest.ts y public/skins/manifest.json declaran por skin:

  • assetsPath
  • templatesPath
  • templatesEntry (ESM dinámico)

Consecuencias

  • Nuevo skin = CSS + assets + registry.js sin rebuild de web-shadcn.
  • Plugins Python siguen declarando solo JSON CUS; no aportan React.
  • Widgets de dominio pueden moverse al bundle del skin operations o paquetes @cortex/widgets-*.

Referencias

  • packages/cortex-panel-core/src/widgets/
  • packages/cortex-panel-shadcn/src/theme/skinTemplateLoader.ts
  • framework/web-shadcn/public/skins/manifest.json