Ejemplos listos
Recetas para copiar. Cada bloque muestra el archivo donde va y pasa la revisión
de la tienda. Después de crear una sección, agrégala en Personalizar tema >
Secciones de la página o en templates/<página>.json.
Banner de promoción
Un banner con título, texto y botón, todo editable en Personalizar tema.
<section class="promo">
<div class="promo-in">
<p class="promo-tag">{{ section.settings.tag }}</p>
<h2>{{ section.settings.title }}</h2>
<p>{{ section.settings.text }}</p>
{%- if section.settings.button_url != blank -%}
<a class="promo-btn" href="{{ section.settings.button_url }}">{{ section.settings.button_label }}</a>
{%- endif -%}
</div>
</section>
{% schema %}
{
"name": "Banner de promoción",
"settings": [
{ "id": "tag", "type": "text", "label": "Etiqueta", "default": "Solo esta semana" },
{ "id": "title", "type": "text", "label": "Título", "default": "Black Friday: hasta 50% off" },
{ "id": "text", "type": "textarea", "label": "Texto", "default": "Kits, VIPs y cosméticos con descuento." },
{ "id": "button_label", "type": "text", "label": "Texto del botón", "default": "Ver ofertas" },
{ "id": "button_url", "type": "url", "label": "Enlace del botón", "default": "/loja" }
]
}
{% endschema %}
.promo { padding: 48px 20px; background: linear-gradient(120deg, hsl(var(--primary)), #1d4ed8); color: #fff; }
.promo-in { max-width: 960px; margin: 0 auto; }
.promo-tag { display: inline-block; padding: 4px 10px; border-radius: 999px; background: rgba(255, 255, 255, .18); font-weight: 700; font-size: 13px; }
.promo h2 { margin: 12px 0 8px; font-size: clamp(28px, 4vw, 44px); }
.promo-btn { display: inline-block; margin-top: 12px; padding: 12px 22px; border-radius: 12px; background: #f5b544; color: #1c1305; font-weight: 700; text-decoration: none; }
Vitrina de una categoría
Los productos de una categoría, con precio, promoción y botón de comprar.
{% load products, category: section.settings.category, limit: section.settings.count as items %}
<section class="showcase">
<h2>{{ section.settings.title }}</h2>
<div class="showcase-grid">
{%- for p in items -%}
<article class="showcase-card">
<a href="{{ p.url }}">
{%- if p.image -%}<img src="{{ p.image }}" alt="{{ p.name }}" loading="lazy">{%- endif -%}
<h3>{{ p.name }}</h3>
</a>
<p class="showcase-price">
{%- if p.on_sale -%}<s>{{ p.original_price | money }}</s> {% endif -%}
<strong>{{ p.price | money }}</strong>
</p>
{%- if p.sold_out -%}
<span class="showcase-off">{{ 'product.sold_out' | t }}</span>
{%- else -%}
<button type="button" data-hystore-add-to-cart="{{ p.id }}">{{ 'product.add' | t }}</button>
{%- endif -%}
</article>
{%- else -%}
<p>{{ 'showcase.empty' | t }}</p>
{%- endfor -%}
</div>
</section>
{% schema %}
{
"name": "Vitrina de categoría",
"settings": [
{ "id": "title", "type": "text", "label": "Título", "default": "Kits" },
{ "id": "category", "type": "text", "label": "Slug de la categoría", "default": "kits" },
{ "id": "count", "type": "range", "label": "Cantidad", "min": 2, "max": 24, "default": 8 }
]
}
{% endschema %}
El slug es el final de la dirección de la categoría en la tienda
(/loja/survival/kits tiene el slug kits). Los textos product.add,
product.sold_out y showcase.empty quedan en los archivos de idioma:
{
"product": { "add": "Comprar", "sold_out": "Agotado" },
"showcase": { "empty": "Todavía no hay productos aquí." }
}
Cuenta regresiva
La tienda completa los números sola, sin JavaScript en el tema.
<section class="countdown" data-hystore-countdown="{{ section.settings.ends_at }}">
<h2>{{ section.settings.title }}</h2>
<div class="countdown-row">
<span><b data-hystore-days>0</b> {{ 'time.days' | t }}</span>
<span><b data-hystore-hours>0</b> {{ 'time.hours' | t }}</span>
<span><b data-hystore-minutes>0</b> {{ 'time.minutes' | t }}</span>
<span><b data-hystore-seconds>0</b> {{ 'time.seconds' | t }}</span>
</div>
</section>
{% schema %}
{
"name": "Cuenta regresiva",
"settings": [
{ "id": "title", "type": "text", "label": "Título", "default": "La nueva temporada empieza en" },
{ "id": "ends_at", "type": "text", "label": "Fecha y hora (UTC)", "default": "2026-12-24T23:59:00Z" }
]
}
{% endschema %}
IP del servidor y jugadores en línea
{% load server_status as status %}
<section class="server-bar">
<button type="button" class="server-ip" data-hystore-copy="{{ store.ip }}">{{ store.ip }}</button>
{%- if status and status.online -%}
<span class="server-on">{{ status.players_online }}/{{ status.players_max }} {{ 'server.online' | t }}</span>
{%- else -%}
<span class="server-off">{{ 'server.offline' | t }}</span>
{%- endif -%}
<hystore-online-players></hystore-online-players>
</section>
{% schema %}
{ "name": "Barra del servidor", "settings": [] }
{% endschema %}
Hacer clic en la IP copia la dirección. La tienda completa
<hystore-online-players> con los jugadores en línea.
Mejores compradores del mes
{% load ranking, period: 'month', limit: 5 as top %}
<section class="top-buyers">
<h2>{{ section.settings.title }}</h2>
<ol>
{%- for row in top -%}
<li>
<img src="{{ row.nick | skin_url: 48 }}" alt="" width="48" height="48">
<span>{{ row.position }}. {{ row.nick }}</span>
<b>{{ row.total_spent | money }}</b>
</li>
{%- endfor -%}
</ol>
</section>
{% schema %}
{
"name": "Mejores compradores",
"settings": [{ "id": "title", "type": "text", "label": "Título", "default": "Top del mes" }]
}
{% endschema %}
Preguntas frecuentes
Un acordeón con preguntas que el dueño de la tienda agrega como bloques.
<section class="faq" data-hystore-accordion="single">
<h2>{{ section.settings.title }}</h2>
{%- for block in section.blocks -%}
<div class="faq-item" data-hystore-accordion-item>
<button type="button" data-hystore-accordion-toggle>{{ block.settings.question }}</button>
<div class="faq-answer" data-hystore-accordion-panel>{{ block.settings.answer }}</div>
</div>
{%- endfor -%}
</section>
{% schema %}
{
"name": "Preguntas frecuentes",
"settings": [{ "id": "title", "type": "text", "label": "Título", "default": "Dudas" }],
"blocks": [
{
"type": "question",
"name": "Pregunta",
"settings": [
{ "id": "question", "type": "text", "label": "Pregunta" },
{ "id": "answer", "type": "textarea", "label": "Respuesta" }
]
}
]
}
{% endschema %}
Colores y opciones del tema
La configuración general queda en theme.json y se vuelve campos en
Personalizar tema:
{
"name": "Mi tema",
"version": "1.0.0",
"color_modes": ["dark", "light"],
"settings": [
{ "id": "accent", "type": "color", "label": "Color de acento", "default": "#f5b544" },
{ "id": "radius", "type": "range", "label": "Redondeo", "min": 0, "max": 28, "default": 14 }
]
}
Los colores y números se vuelven variables CSS en la raíz del tema:
.button { background: var(--theme-accent); border-radius: calc(var(--theme-radius) * 1px); }
html:not(.dark) .card { background: #fff; color: #0b1526; }
html.dark .card { background: #0d1524; color: #e8eef8; }
Y cualquier configuración general aparece en Liquid como {{ settings.accent }}.
Cambiar modo de color e idioma
<div class="header-tools">
<button type="button" data-hystore-color-mode="toggle">{{ 'header.theme' | t }}</button>
<button type="button" data-hystore-language="pt">PT</button>
<button type="button" data-hystore-language="en">EN</button>
<button type="button" data-hystore-language="es">ES</button>
<button type="button" data-hystore-open="cart">{{ 'header.cart' | t }} (<span data-hystore-cart-count>0</span>)</button>
<hystore-account></hystore-account>
</div>
Úsalo en el layout con {% render 'header-tools' %}.
Más
- La guía del tema lista todos los datos, filtros, bloques listos y piezas interactivas.
- Para JavaScript (ruleta, quiz, calculadora), mira Apps aisladas.
- Los temas Base, Aurora, Celeste y Prisma son excelentes para estudiar: empieza uno en el panel y abre sus archivos en el editor.
