Saltar al contenido principal

Arquitectura del sistema de temas

OmniBuy usa un sistema de overlay en 4 capas para resolver los archivos de un tema. Cada tema solo necesita shipear los archivos que cambia; el resto se hereda de las capas inferiores.

Las 4 capas

Capa 4 (máxima prioridad) themes/<tu-tema>/ → Solo overrides
Capa 3 themes/dawn/ → Tema referencia completo
Capa 2 themes/_base/ → Secciones compartidas (header, hero)
Capa 1 (mínima prioridad) themes/_platform/ → Snippets y JS de addons

Cuando el motor de render busca un archivo (por ejemplo, sections/hero.html), recorre las capas de abajo hacia arriba. La primera capa que lo encuentre gana.

_platform — Addons compartidos

Contiene snippets y assets que usan los addons del marketplace (AR Try-On, Hair Color Try-On). Está en la capa más baja porque es código compartido entre todos los temas.

themes/_platform/
├── addons/
│ ├── ar-tryon.js
│ ├── hair-tryon-vto.js
│ └── hair-tryon.css
└── snippets/
└── ar-tryon-panel.html

_base — Secciones y assets globales

Las secciones más complejas viven aquí: header.html (1240 líneas, 25+ variantes) y hero.html (499 líneas, 10 variantes). Todos los temas heredan estas secciones.

themes/_base/
├── sections/
│ ├── header.html (25 variantes: classic-split, mega-menu, centered-brand…)
│ └── hero.html (10 variantes: carousel, full-bleed, video…)
├── assets/
│ ├── header-variants.css
│ ├── hero-variants.css
│ ├── hero-variants.js
│ └── alpine.min.js
└── snippets/
├── breadcrumb.html
├── css_vars.html
├── product-card.html
└── seo_head.html

dawn — Tema referencia

El tema completo con todas las secciones, templates, snippets, locales y configuración. Un tema personalizado solo shipea los archivos que overridea.

themes/dawn/
├── theme.json (declara sections[], addons[], templates[])
├── config/
│ ├── settings_schema.json
│ └── settings_data.json
├── sections/ (25 módulos de contenido)
├── snippets/ (12 snippets reutilizables)
├── templates/ (21 templates: index, product, cart…)
├── locales/ (es.json, en.json)
└── assets/

<tu-tema> — Solo overrides

Un tema como cielo o olive-luxe es liviano. Solo shipea lo que cambia:

themes/cielo/
├── theme.json (declara industry, sections[], addons[])
├── sections.json (schema del visual editor)
├── config/
├── snippets/ (solo los que overridea dawn)
├── templates/ (solo los que cambia)
├── locales/
└── assets/

Cielo, por ejemplo, no tiene sections/header.html ni sections/hero.html. Los hereda de _base y funcionan con las mismas variantes.

Cómo se resuelve un archivo

El algoritmo en internal/storefront/engine/theme_source.go:

  1. Se construye un floorFS mergesando _platform_basedawn (si el tema no es dawn).
  2. Se overlayea el tema solicitado encima del floor.
  3. El resultado es un fstest.MapFS en memoria donde el tema gana en caso de conflicto de paths.
floorFS = overlay(_platform, _base)
floorFS = overlay(floorFS, dawn) // si tema ≠ dawn
merged = overlay(floorFS, tu-tema) // tu tema gana

Per-tenant overrides (Theme Editor)

Además de los archivos del tema, cada tenant puede tener overrides guardados en GCS:

themes/tenants/<tenant_id>/<theme_name>/overrides/<path>

Estos overrides se aplican encima del tema mergeado, tanto en preview como en producción. El Theme Editor (code editor) los crea cuando un merchant edita un archivo .html, .css o .js.

ThemeLoader — el pipeline completo

El ThemeLoader resuelve archivos en este orden:

  1. TenantThemeSource — overrides del tenant en GCS + drafts
  2. ReleaseThemeSource — snapshot publicado de la release actual
  3. LocalThemeSource — overlay de 4 capas en el filesystem

Temas disponibles

TemaIndustriaDescripción
dawnGeneralTema referencia completo, base para todos
cieloModaVisual editor con 13 secciones propias, variantes de header/hero
olive-luxeLujoHeader centered-brand, hero video full-bleed, drawer acordeón
boldGeneralTema legacy con settings inline de color/tipografía
minimalGeneralTema legacy minimalista