Temas Liquid

Guía completa para crear temas Liquid en Karrito. Motor de plantillas, filtros, tags, bloques, live-edit y el editor visual.

9 min de lecturaguia, liquid, temas, desarrollador, avanzadoActualizado: 3 de abril de 2026

Qué es un tema Liquid

Los temas Liquid son plantillas HTML con variables dinamicas que se renderizan en el servidor. Son la base del marketplace de temas de Karrito. Si conoces Shopify, ya conoces la sintaxis.

Karrito tiene dos motores de temas:

  • Veloz (React) — El tema por defecto. Editor visual completo con 40 secciones (6 en el plan gratis).
  • Liquid — Motor de plantillas para temas personalizables. Editor basado en schemas.

Estructura de un tema

themes/mi-tema/
  config/
    settings_schema.json    <- Settings editables (colores, fonts, layout)
    settings_data.json      <- Valores por defecto
  layout/
    theme.liquid            <- Layout principal (HTML, head, body)
  locales/
    es.default.json         <- Traducciones
  sections/
    header.liquid           <- Secciones con {% schema %}
    hero.liquid
    product-grid.liquid
    footer.liquid
  snippets/                 <- Fragmentos reutilizables del tema
    mi-componente.liquid
  templates/
    index.json              <- Homepage (que secciones, en que orden)
    product.json            <- Pagina de producto
    collection.json         <- Pagina de coleccion
    search.json             <- Busqueda
    404.json                <- Pagina no encontrada
    policy.json             <- Politicas

Objetos disponibles

shop / store

Datos de la tienda.

Campo Tipo Descripción
shop.name string Nombre de la tienda
shop.url string URL del subdominio
shop.description string Descripción
shop.logo string URL del logo
shop.currency string Código de moneda (USD, MXN, etc.)
shop.money_format string Formato de precio (${{amount}})
store.whatsapp_number string Número de WhatsApp

product

Disponible en la página de producto. Interfaz dual (nativa + Shopify compat).

Campo Tipo Descripción
product.title / product.name string Nombre
product.handle / product.slug string URL slug
product.url string /products/slug
product.description string Descripción
product.price number Precio en centavos
product.price_display string Precio como decimal ("25.00")
product.compare_at_price number/null Precio anterior
product.featured_image object/null { src, alt }
product.images array [{ src, alt, position }]
product.available boolean Disponible
product.badge string/null Badge (Nuevo, Oferta, etc.)
product.avg_rating number Promedio de reseñas (0-5)
product.review_count number Total de reseñas
product.variants array Variantes del producto
product.options array Nombres de opciones (["Color", "Talla"])
product.options_with_values array [{ name, values }]
product.selected_or_first_available_variant object/null Primera variante activa
product.has_only_default_variant boolean Si no tiene variantes
product.type string Tipo (categoría principal)
product.vendor string Vendedor (nombre de tienda)
product.tags array Tags del producto

collection / category

Disponible en páginas de colección.

Campo Tipo Descripción
collection.title / collection.name string Nombre
collection.handle / collection.slug string URL slug
collection.url string /collections/slug
collection.image object/null { src, alt }
collection.products array Productos de la colección
collection.products_count number Total

Globals

Variable Descripción
products Todos los productos activos
categories / collections Todas las categorías
settings Settings del tema (colores, fonts, etc.)
page_title Título de la página
page_description Meta description
canonical_url URL canonica
current_page Página actual (para paginación)
powered_by_link HTML del footer de branding

Filtros custom

Precios

{{ product.price | money }}                    <!-- $25.00 -->
{{ product.price | money_without_trailing_zeros }}  <!-- $25 -->
{{ product.price | money_with_currency }}      <!-- $25.00 USD -->

URLs

{{ "base.css" | asset_url }}         <!-- /liquid/assets/base.css -->
{{ product.featured_image.src | image_url: width: 500 }}
{{ "Hola Mundo" | url_encode }}      <!-- Hola%20Mundo -->

Strings

{{ 'products.add_to_cart' | t }}          <!-- Agregar al carrito -->
{{ 'cart.item_count' | t: count: 5 }}     <!-- 5 productos en tu carrito -->
{{ "Mi Producto!" | handle }}              <!-- mi-producto -->
{{ 5 | pluralize: "producto", "productos" }}  <!-- productos -->

Colores

{{ "#10B981" | color_lighten: 20 }}    <!-- Aclara 20% -->
{{ "#10B981" | color_darken: 10 }}     <!-- Oscurece 10% -->
{{ "#ff0000" | color_mix: "#0000ff", 50 }}  <!-- Mezcla 50% -->
{{ "#fff" | color_contrast: "#000" }}  <!-- 21 (ratio WCAG) -->

HTML

{{ "img.jpg" | image_tag }}           <!-- <img src="img.jpg" loading="lazy"> -->
{{ "Ver mas" | link_to: "/products" }}  <!-- <a href="/products">Ver mas</a> -->

Fonts

{{ "montserrat_n4" | font_face }}   <!-- @font-face CSS -->
{{ "poppins_n4" | font_url }}       <!-- URL de Google Fonts -->

Tags custom

{% style %} / {% endstyle %}

Renderiza un bloque <style> con variables Liquid.

{% style %}
  .hero { background: {{ section.settings.color_bg }}; }
{% endstyle %}

{% javascript %} / {% endjavascript %}

Renderiza un bloque <script>.

{% form %} / {% endform %}

Genera un <form> wrapper.

{% schema %} / {% endschema %}

Define los settings editables de una sección. Se muestra en el ThemeStudio.

{% schema %}
{
  "name": "Hero",
  "settings": [
    { "type": "text", "id": "heading", "label": "Titulo", "default": "" },
    { "type": "textarea", "id": "subheading", "label": "Subtitulo" },
    { "type": "range", "id": "columns", "label": "Columnas", "min": 2, "max": 4, "default": 3 },
    { "type": "color", "id": "bg_color", "label": "Fondo", "default": "#ffffff" },
    { "type": "checkbox", "id": "show_badge", "label": "Mostrar badge", "default": true },
    { "type": "select", "id": "font", "label": "Fuente", "options": [
      { "value": "outfit", "label": "Outfit" },
      { "value": "inter", "label": "Inter" }
    ]}
  ]
}
{% endschema %}

{% paginate %} / {% endpaginate %}

Página una colección.

{% paginate products by 12 %}
  {% for product in products %}
    <!-- renderizar producto -->
  {% endfor %}

  {% if paginate.pages > 1 %}
    <nav>
      {% if paginate.previous %}
        <a href="{{ paginate.previous.url }}">Anterior</a>
      {% endif %}
      {% for part in paginate.parts %}
        {% if part.is_link %}
          <a href="{{ part.url }}">{{ part.title }}</a>
        {% else %}
          <span>{{ part.title }}</span>
        {% endif %}
      {% endfor %}
      {% if paginate.next %}
        <a href="{{ paginate.next.url }}">Siguiente</a>
      {% endif %}
    </nav>
  {% endif %}
{% endpaginate %}

Settings schema

Los settings del tema se definen en config/settings_schema.json:

[
  {
    "name": "Colores",
    "settings": [
      { "type": "color", "id": "color_primary", "label": "Color principal", "default": "#10B981" },
      { "type": "color", "id": "color_bg", "label": "Fondo", "default": "#ffffff" }
    ]
  },
  {
    "name": "Tipografia",
    "settings": [
      { "type": "select", "id": "font_heading", "label": "Fuente titulos", "options": [
        { "value": "outfit", "label": "Outfit" },
        { "value": "inter", "label": "Inter" }
      ]}
    ]
  }
]

Los settings se acceden en templates como {{ settings.color_primary }} y se convierten automáticamente en CSS variables (--color-primary).

Shared snippets

Los snippets compartidos viven en themes/_shared/snippets/ y están disponibles para todos los temas:

Snippet Descripción
karrito-product-card Card de producto con imagen, precio, badge
karrito-price Precio con descuento
karrito-star-rating Estrellas de rating
karrito-variant-selector Selector de variantes (color, talla)
karrito-color-swatches Swatches de colores
karrito-product-gallery Galería de imágenes con thumbnails
karrito-trust-badges Badges de confianza
karrito-share Botones de compartir
karrito-breadcrumb Migas de pan
karrito-reviews Display de reseñas
karrito-whatsapp-fab Boton flotante de WhatsApp

Uso:

{% render 'karrito-star-rating', rating: product.avg_rating, count: product.review_count %}
{% render 'karrito-breadcrumb', current_page: product.title %}

CSS variables

Los settings de color y tipografía se inyectan como CSS variables en :root:

--color-bg: #ffffff;
--color-text: #0f172a;
--color-primary: #10B981;
--color-secondary: #64748b;
--color-surface: #f8fafc;
--color-border: #e2e8f0;
--font-heading: 'Outfit', sans-serif;
--font-body: 'Outfit', sans-serif;
--border-radius: 12px;

Siempre usa CSS variables con fallbacks: color: var(--color-text, #0f172a).

karrito-cart.js

El script karrito-cart.js se inyecta automáticamente en todo tema Liquid. Provee:

  • Cart drawer con 3 vistas (carrito, checkout, confirmación WhatsApp)
  • Free shipping bar
  • Shipping selector
  • Search overlay (Cmd+K)
  • KarritoCart.add(productId, quantity, variantId) — API publica

No necesitas implementar el carrito — ya esta incluido.

Bloques (blocks)

Los bloques son contenido repetible dentro de una sección. Ejemplo: testimonios, features, slides.

Definir bloques en el schema:

{% schema %}
{
  "name": "Testimonios",
  "settings": [],
  "blocks": [
    {
      "type": "testimonial",
      "name": "Testimonio",
      "settings": [
        { "type": "text", "id": "author", "label": "Autor" },
        { "type": "textarea", "id": "text", "label": "Texto" }
      ]
    }
  ],
  "max_blocks": 6
}
{% endschema %}

Usar bloques en el template:

{% for block in section.blocks %}
  <div>
    <p>"{{ block.settings.text }}"</p>
    <strong>— {{ block.settings.author }}</strong>
  </div>
{% endfor %}

Los bloques se definen en el template JSON:

{
  "type": "testimonials",
  "settings": {},
  "blocks": {
    "block_1": { "type": "testimonial", "settings": { "author": "Maria", "text": "Excelente!" } },
    "block_2": { "type": "testimonial", "settings": { "author": "Carlos", "text": "Muy bueno" } }
  },
  "block_order": ["block_1", "block_2"]
}

Live-edit (ThemeStudio)

Cuando un usuario edita settings desde el ThemeStudio, los cambios se reflejan en tiempo real sin recargar la página.

Para que tus secciones sean compatibles con live-edit:

  1. Usa CSS variables para colores, fonts y bordes. Los cambios de diseño se aplican instantaneamente via CSS.
  2. Mantiene el wrapper karrito-section. Cada sección se envuelve automáticamente en <div id="karrito-section-{id}" class="karrito-section" data-section-type="{type}">.
  3. No dependas de <script> dentro de secciones. Cuando se hace hot-swap, los scripts inline NO se re-ejecutan. Usa event delegation o karrito-cart.js.

Flujo de cambios:

  • Color/font/radius → CSS variable update instantaneo (~0ms)
  • Texto/imagen → Re-render parcial de la sección via API (~200ms)
  • Reorder → Animación FLIP local (~0ms)
  • Agregar/quitar sección → Render + inyección animada (~300ms)

Templates JSON

Los templates definen que secciones aparecen en cada página:

{
  "sections": {
    "header": { "type": "header", "settings": {} },
    "hero": { "type": "hero", "settings": { "heading": "", "subheading": "" } },
    "grid": { "type": "product-grid", "settings": { "columns": 3 } },
    "footer": { "type": "footer", "settings": {} }
  },
  "order": ["header", "hero", "grid", "footer"]
}

El store owner puede personalizar los settings y el orden de secciones desde el ThemeStudio.