Saltar al contenido

Arquitectura de temas de Shopify que aguanta un año

Un tema no se degrada por Liquid mal escrito, sino por un puñado de decisiones estructurales que se toman en la segunda semana, cuando nadie está pensando en el mes once.

Guía6 de mayo de 20268 min de lectura

Un tema de Shopify casi nunca se rompe. Se degrada, y se degrada de una forma muy concreta: el editor de temas deja de ser el lugar donde ocurren los cambios, y cada cambio de contenido se convierte en un ticket para un desarrollador. Las páginas siguen renderizando. La tienda sigue vendiendo. Pero lo que realmente se compró — un storefront que el equipo del comerciante puede operar — ya no está, y recuperarlo suele costar más que el desarrollo original.

Esa degradación casi nunca la causa un Liquid mal escrito. La causan unas pocas decisiones de arquitectura de las primeras dos semanas, cuando la presión es tener una home en pantalla. Estas son, y hacia dónde conviene tomarlas.

La sección es la unidad de la página; el block es la unidad de la fila

Online Store 2.0 permite poner secciones en todas las plantillas, y la lectura habitual de eso es permiso para volver sección a todo. No lo es. Una sección es una banda horizontal de la página que el comerciante podría reordenar, quitar o colocar una sola vez. Un block es un elemento repetido dentro de esa banda cuya cantidad controla el comerciante.

La prueba es la cardinalidad. Si el comerciante alguna vez va a querer dos de algo, uno al lado del otro, es un block. Si va a querer exactamente uno, en una posición concreta de la pila, es una sección. Equivocarse aquí es el error estructural más común en desarrollo de temas, y es caro porque queda invisible durante meses.

Una tira de tres columnas hecha como tres secciones separadas se ve idéntica en el editor el día uno. El día sesenta alguien quitó la columna del medio y dejó un hueco, las tres se separaron en padding, y cambiar el encabezado son tres ediciones. La misma tira como una sola sección feature-strip con un block feature y max_blocks: 4 es la misma página con la cuarta parte de superficie que mantener.

El schema es una interfaz, no un cajón

Cada setting que agregas al schema de una sección es una promesa de que ese setting funciona combinado con todos los demás settings de esa sección. Diez booleanos independientes no son diez estados, son mil veinticuatro, y habrás probado unos seis. Los settings son baratos de agregar y permanentes de soportar.

Así que pocos y de comportamiento. layout: grid | carousel es un buen setting: nombra una intención, tiene un conjunto acotado de valores, y cada valor es una ruta de código que alguien escribió a propósito. column_gap_px es malo: le entrega una decisión de diseño a alguien que no está tomando decisiones de diseño, y garantiza que seis meses de ediciones pequeñas dejen el sitio ligeramente inconsistente en todas partes.

Desliza la figura para verla completa

Settings o metafields: de quién es el valor

Esta es la decisión que separa un tema que puedes reemplazar de un tema con el que te casaste, y tiene una prueba limpia. Exporta el tema, instálalo en otra tienda, y pregunta si el valor debería viajar con él. Si sí, va en settings del schema. Si el valor describe un producto, una colección, una página o un market, es dato de la tienda y va en un metafield.

Unas instrucciones de cuidado escritas en los settings de sección de la plantilla de producto son un valor que vive dentro del tema. Aplican al producto que use esa plantilla, no se pueden exportar, ni editar en masa, y solo se traducen en Translate & Adapt cuando están tipados como text, richtext o inline_richtext, y desaparecen el día que se cambia el tema. Ese mismo texto como product.metafields.custom.care_instructions pertenece al producto. Sobrevive al tema, se edita en el admin junto a todo lo demás de ese producto, una operación masiva puede llenarlo, y una app o una exportación pueden leerlo.

La regla de trabajo: todo lo que varía por producto, por colección o por market es dato. Todo lo que describe cómo el tema presenta el dato es un setting. En el momento en que te descubres escribiendo un setting cuya etiqueta empieza con el nombre de un producto concreto, cruzaste la línea y conviene parar.

Metaobjects para las formas que se repiten

Cuando la misma cosa estructurada aparece contra muchos productos — una guía de tallas, un ingrediente, una certificación, un símbolo de cuidado — no es un metafield por producto, es un metaobject con una referencia apuntándole. Eso te da un único lugar donde editar la definición de "algodón orgánico" y todos los productos que la referencian se actualizan. Modelarlo el día uno cuesta una hora; retroajustarlo cuando doscientos productos ya tienen el texto pegado en un metafield de rich text cuesta una semana. Es el tipo de trabajo al que nuestros proyectos de desarrollo Shopify dedican tiempo antes de que nadie abra una plantilla.

Desliza la figura para verla completa

Snippets, y el copy-paste que se come un tema

Render de precio. Tarjetas de producto. Lógica de badges. Texto de disponibilidad por variante. Esos son los cuatro lugares donde se acumula la duplicación, y la duplicación no es un problema de prolijidad — es un problema de corrección con retardo. El costo de un copy-paste nunca es el duplicado. Es el día en que cambia la regla de visualización de impuestos, o hay que mostrar precio por unidad, o un badge de oferta necesita una condición nueva, y el cambio tiene que caer en siete lugares, y cae en seis.

Usa render y no include, con criterio. El scoping es el punto: un snippet renderizado con parámetros declarados es una función, y una función se revisa leyéndola. Un snippet que alcanza section.settings por su cuenta, o que asume que hay un objeto product en scope, no es un snippet — es un fragmento de una sección que se va a romper la primera vez que lo rendericen desde otra.

Un buen snippet tiene pocos parámetros, ningún conocimiento de desde dónde lo llamaron, y un comentario arriba diciendo qué espera. Tres líneas de documentación al principio de price.liquid es el mantenimiento más barato que existe.

Dónde vive el JavaScript

El JavaScript de un tema tiene una restricción estructural que se olvida hasta que muerde: las secciones se vuelven a renderizar. El editor intercambia el markup de una sección en vivo, y la Section Rendering API lo reemplaza en el storefront durante actualizaciones de carrito y filtrado. Cualquier listener atado una vez en DOMContentLoaded dentro de una sección apunta a un nodo que ya no existe.

La respuesta es atar el comportamiento al markup y no a la carga de la página. Un custom element cuyo connectedCallback hace el cableado lo reinicializa el navegador solo, cada vez que ese markup reaparece, sin contabilidad de tu lado. Un comportamiento, un custom element, un archivo, junto a la sección que lo usa. Es la estructura que usa Dawn y es la correcta por razones que no tienen nada que ver con la moda.

La otra decisión es si poner un build delante del tema. Un tema se sirve desde el CDN de Shopify y no necesita bundler; agregar uno te da TypeScript y resolución de módulos, y te cuesta un artefacto compilado en el repositorio y una depuración a una capa de distancia de lo que se publica. Ambas respuestas son defendibles. Lo que no es defendible es un bundler que nadie documentó: así termina un tema con un directorio dist que nadie se atreve a regenerar.

Las decisiones que pudren un tema

En concreto, ordenadas por daño:

  1. Secciones atadas a una página. Una sección llamada homepage-hero es una sección que se va a duplicar como landing-hero la primera vez que marketing necesite una. Nombra las secciones por lo que son, no por dónde se usaron primero.
  2. Datos de producto en settings de sección. Ya cubierto, y es el que convierte una migración de tema en un proyecto de recuperación de datos.
  3. Plantillas duplicadas. Dos plantillas de producto casi idénticas son dos lugares donde arreglar todo. Las plantillas alternas con sufijo son para estructuras de página distintas, no para un encabezado distinto.
  4. JavaScript global atado a la carga. Funciona en el primer render y deja de funcionar en silencio tras cualquier re-render de sección, o sea que está roto justo donde el comerciante menos prueba.
  5. Valores en píxeles en el schema. Cada uno es una inconsistencia futura con el nombre de un comerciante encima.
  6. No borrar nunca. Secciones que nadie usa, settings que nada lee, snippets que nada renderiza. El código muerto en un tema es peor que en una app, porque el editor de temas se lo sigue ofreciendo al comerciante.
  7. Editar el tema en vivo. Un solo cambio sin versionar basta para volver mentiroso al repositorio, y después de eso nadie vuelve a confiar en un despliegue.

Cómo se ve realmente un tema mantenible al año

Un tema mantenible no es uno con Liquid ingenioso. Es uno donde una página nueva se compone en el editor sin un desarrollador, donde los datos de producto viven en los productos, donde cambiar la visualización del precio es un archivo, y donde un desarrollador que nunca vio el tema encuentra el código detrás de cualquier banda en menos de un minuto leyendo el nombre de su sección.

Es una vara baja al describirla y rara en la práctica, porque cada una de esas propiedades es el resultado de una decisión que alguien se negó a posponer. La misma disciplina aplicada a velocidad da el mismo argumento en el trabajo de rendimiento: lo caro nunca es el arreglo, es la arquitectura que lo hizo falta. Nuestro trabajo de desarrollo de temas empieza en esa capa por la misma razón.

Blog