Temas Liquid

Guia 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

Que 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 28+ secciones.
  • 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 Descripcion
shop.name string Nombre de la tienda
shop.url string URL del subdominio
shop.description string Descripcion
shop.logo string URL del logo
shop.currency string Codigo de moneda (USD, MXN, etc.)
shop.money_format string Formato de precio (${{amount}})
store.whatsapp_number string Numero de WhatsApp

product

Disponible en la pagina de producto. Interfaz dual (nativa + Shopify compat).

Campo Tipo Descripcion
product.title / product.name string Nombre
product.handle / product.slug string URL slug
product.url string /products/slug
product.description string Descripcion
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 resenas (0-5)
product.review_count number Total de resenas
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 (categoria principal)
product.vendor string Vendedor (nombre de tienda)
product.tags array Tags del producto

collection / category

Disponible en paginas de coleccion.

Campo Tipo Descripcion
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 coleccion
collection.products_count number Total

Globals

Variable Descripcion
products Todos los productos activos
categories / collections Todas las categorias
settings Settings del tema (colores, fonts, etc.)
page_title Titulo de la pagina
page_description Meta description
canonical_url URL canonica
current_page Pagina actual (para paginacion)
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 seccion. 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 %}

Pagina una coleccion.

{% 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 automaticamente en CSS variables (--color-primary).

Shared snippets

Los snippets compartidos viven en themes/_shared/snippets/ y estan disponibles para todos los temas:

Snippet Descripcion
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 Galeria de imagenes con thumbnails
karrito-trust-badges Badges de confianza
karrito-share Botones de compartir
karrito-breadcrumb Migas de pan
karrito-reviews Display de resenas
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 tipografia 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 automaticamente en todo tema Liquid. Provee:

  • Cart drawer con 3 vistas (carrito, checkout, confirmacion 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 seccion. 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 pagina.

Para que tus secciones sean compatibles con live-edit:

  1. Usa CSS variables para colores, fonts y bordes. Los cambios de diseno se aplican instantaneamente via CSS.
  2. Mantiene el wrapper karrito-section. Cada seccion se envuelve automaticamente 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 seccion via API (~200ms)
  • Reorder → Animacion FLIP local (~0ms)
  • Agregar/quitar seccion → Render + inyeccion animada (~300ms)

Templates JSON

Los templates definen que secciones aparecen en cada pagina:

{
  "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.