`.
## `sections/{header,footer}-group.json`
Los grupos de encabezado y pie envuelven todas las páginas — incluidas las rutas propias del framework como el checkout de carrito. Formato igual a una plantilla, más `type`, `name` y el opcional `sticky`:
```json theme={null}
{
"type": "header",
"name": "Encabezado",
"sticky": false,
"sections": {
"announcement-1": { "type": "announcement-bar", "settings": {} },
"header-1": { "type": "header", "settings": { "menu": "main-menu" } }
},
"order": ["announcement-1", "header-1"]
}
```
## `snippets/`
Parciales invocados con `{% render 'nombre' %}`. Como en el Shopify moderno, `render` es aislado: el snippet solo ve los argumentos que le pasas.
```liquid theme={null}
{%- render 'product-card', product: card, section_id: section.id -%}
```
No nombres un argumento de `render` igual que una clave global (`settings`, `cart`, `shop`, …) ni que una meta-propiedad de Liquid como `size` — colisionan al resolverse dentro del snippet. Usa nombres propios: `card_size`, `items_per_row`.
## `assets/`
Archivos estáticos servidos desde el CDN. `assets/theme.css` y `assets/theme.js` se enlazan **automáticamente** en todas las páginas — no hay `theme.liquid` donde enlazarlos a mano. El resto de assets se referencia con el filtro `asset_url`:
```liquid theme={null}

```
# Carrito AJAX y secciones
Source: https://docs.riqra.com/temas/cart-ajax-y-secciones
Los endpoints AJAX del carrito, el Section Rendering API y los eventos del tema.
El JavaScript del tema habla con la tienda por endpoints al estilo Shopify. Todos los montos son **centavos enteros** y todas las respuestas de carrito comparten una misma forma (el carrito completo), también en `add.js`.
| Endpoint | Método | Para qué |
| ----------------------- | ------ | ---------------------------------------------------------------------- |
| `/cart.js` | GET | Leer el carrito actual. |
| `/cart/add.js` | POST | Agregar una variante. |
| `/cart/change.js` | POST | Cambiar la cantidad de una línea (0 la elimina). |
| `/cart/update.js` | POST | Cambiar varias líneas en un solo request. |
| `/cart/clear.js` | POST | Vaciar el carrito. |
| `/cart/add` | POST | Fallback sin JavaScript de `{% form 'product' %}`; redirige a `/cart`. |
| `/products/{handle}.js` | GET | JSON del producto (variantes, precios, disponibilidad). |
| `/api/sections` | GET | Re-renderizar secciones de una ruta (Section Rendering API). |
## Leer el carrito
```js theme={null}
const cart = await fetch("/cart.js").then((res) => res.json());
// { token, item_count, items: [...], total_price, original_total_price, total_discount, currency }
```
Cada línea trae `id`, `variant_id`, `quantity`, `title`, `variant_title`, `sku`, `price`, `line_price`, `final_line_price`, `image`, `url` y `available`.
## Escribir en el carrito
Los cuatro endpoints de escritura aceptan JSON (o form-encoded) y responden con el carrito completo:
```js theme={null}
// Agregar: id = id de variante
await fetch("/cart/add.js", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ id: variantId, quantity: 2 }),
});
// Cambiar una línea; quantity: 0 la elimina
await fetch("/cart/change.js", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ id: variantId, quantity: 0 }),
});
// Varias líneas de una vez
await fetch("/cart/update.js", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ updates: { [variantIdA]: 3, [variantIdB]: 0 } }),
});
```
Un error de negocio (sin stock, cantidad inválida) responde `422` con `{ status, message, description }`.
Después de cada escritura exitosa, anuncia el cambio al resto del tema:
```js theme={null}
window.dispatchEvent(new Event("riqra:cart-changed"));
```
## Secciones re-renderizadas en la misma respuesta
Igual que en Shopify, las escrituras aceptan un parámetro `sections` para que la respuesta incluya el HTML actualizado de las secciones que nombres — un solo round-trip actualiza estado y DOM:
```js theme={null}
const res = await fetch("/cart/add.js", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
id: variantId,
quantity: 1,
sections: "cart-1,header-1",
sections_url: "/cart",
}),
}).then((r) => r.json());
// res.sections → { "cart-1": "
…
", "header-1": "…" }
```
`sections_url` es la ruta contra la que se renderizan (por defecto `/cart`). Cada fragmento llega con su wrapper `riqra-section-{id}` incluido: reemplaza el nodo completo.
## Section Rendering API
Fuera de las escrituras de carrito, `GET /api/sections` re-renderiza secciones de cualquier ruta con superficie de tema — filtros de colección, mini-carrito, etc.:
```js theme={null}
const sections = await fetch(
`/api/sections?path=${encodeURIComponent("/collections/ofertas?brand=acme")}§ions=main-collection`,
).then((res) => res.json());
// { "main-collection": "
…
" }
```
A diferencia de Shopify, `?sections=` no se intercepta sobre las URLs de página: usa siempre este endpoint.
Al reemplazar el HTML de una sección, despacha `riqra:section:load` sobre el nodo nuevo para que los scripts que escuchan ese evento se re-inicialicen (los custom elements se re-montan solos):
```js theme={null}
function swapSection(id, html) {
const target = document.getElementById(`riqra-section-${id}`);
if (!target || typeof html !== "string") return;
target.outerHTML = html;
document
.getElementById(`riqra-section-${id}`)
?.dispatchEvent(new Event("riqra:section:load", { bubbles: true }));
}
```
El personalizador del panel usa este mismo evento cuando refresca secciones en la vista previa.
## Eventos del tema
| Evento | Se despacha | Escúchalo para |
| -------------------- | -------------------------------------------------- | ------------------------------------------------------- |
| `riqra:cart-changed` | En `window`, tras cualquier escritura de carrito. | Refrescar el contador del header, el mini-carrito, etc. |
| `riqra:section:load` | Sobre una sección cuyo HTML acaba de reemplazarse. | Re-inicializar listeners no basados en custom elements. |
Origin resume el patrón completo — un snapshot compartido del carrito, invalidado por el evento:
```js theme={null}
let cartSnapshot = null;
function readCart() {
cartSnapshot ??= fetch("/cart.js")
.then((res) => (res.ok ? res.json() : null))
.catch(() => null);
return cartSnapshot;
}
window.addEventListener("riqra:cart-changed", () => {
cartSnapshot = null;
});
```
## JSON de producto
Para pickers de variantes o vistas rápidas:
```js theme={null}
const product = await fetch(`/products/${handle}.js`).then((res) => res.json());
// { id, title, handle, url, vendor, available, price, price_min, price_max,
// compare_at_price, images, featured_image, variants: [...] }
```
`compare_at_price` mayor que `price` es la señal de oferta — los badges de descuento se derivan de esa comparación, no de un objeto de promociones.
# Ciclo de desarrollo
Source: https://docs.riqra.com/temas/ciclo-de-desarrollo
Del borrador con dev a la tienda del cliente: push, riqra.theme.json y la entrega a producción.
## El bucle de desarrollo
`riqra-theme dev` es el bucle diario. En cada guardado el CLI valida el tema (el mismo `check` que corre el servidor), lo comprime y sube un **tema de desarrollo** con su instalación en borrador:
```text theme={null}
$ riqra-theme dev
Watching /work/mi-tema
Preview: https://acme.riqra.site/?preview_theme_id=…&preview_token=…
Draft install expires 2026-07-25T14:02:11.000Z
✓ updated 14:02:11
```
* La URL de vista previa renderiza el borrador solo para quien la tiene; el resto de visitantes sigue viendo el tema publicado.
* La página de vista previa detecta cada push y se recarga sola — no necesitas refrescar.
* Si `check` falla, el CLI imprime los diagnósticos y espera el siguiente guardado; no sube nada roto.
El tema de desarrollo y su borrador expiran a los **7 días**. Cada push de `dev` renueva el plazo, así que solo caduca si dejas de trabajar; al expirar, la plataforma lo elimina y `dev` crea uno nuevo en el siguiente arranque.
## Publicar una versión con `push`
Cuando el trabajo está listo para compartirse, `push` sube el tema con su identidad definitiva:
```bash theme={null}
riqra-theme push --theme acme-2026
```
```text theme={null}
✓ Pushed acme-2026 (version 3f9c21ab)
```
* El slug se pasa con `--theme` la primera vez; un push exitoso lo guarda en `riqra.theme.json` y los siguientes ya no lo necesitan.
* Cada push calcula una versión por contenido (`versionHash`). Re-subir sin cambios es un no-op barato.
* Un push **reemplaza el contenido del tema en su lugar**: toda tienda que lo tenga instalado pasa a servir la nueva versión.
### `riqra.theme.json`
Archivo de proyecto del tema, versionado junto al código:
```json theme={null}
{
"theme": {
"slug": "acme-2026"
}
}
```
`push` y `pull` lo leen para saber sobre qué tema operar, y `push` lo actualiza tras la primera subida.
## Entrega a producción
Subir nunca publica. La entrega a la tienda del cliente está mediada por Riqra:
1. La agencia hace `push` del tema final; queda disponible en el registro de la organización.
2. El staff de Riqra lo instala en la tienda del cliente como instalación **no publicada**.
3. El comerciante (o el staff) revisa, personaliza y lo **activa** desde el panel. La activación es un intercambio atómico: el tema anterior pasa a no publicado y conserva su personalización.
## Versionado: no hay
Un tema no tiene versiones ni migraciones. Re-subir actualiza en su lugar, así que cada push debe ser compatible con la personalización que el comerciante ya guardó (mismos ids de settings, mismos tipos de sección). Un rediseño incompatible no se sube encima: se entrega como **un tema nuevo** con otro slug, se instala junto al actual y se activa cuando el cliente esté listo.
# Introducción
Source: https://docs.riqra.com/temas/introduccion
Qué es un tema de Riqra y cómo se reparte el trabajo entre la agencia, Riqra y el comerciante.
Un tema define la cara de una tienda online de Riqra: un árbol de archivos Liquid + JSON que la plataforma valida al subirse, almacena e interpreta en el servidor en cada request. No compilas ni despliegas código — el tema es datos subidos y la plataforma es quien lo ejecuta.
Si vienes de Shopify, la gramática te va a resultar familiar a propósito: secciones OS 2.0 con `{% schema %}`, plantillas JSON, `settings_schema.json`, snippets con `{% render %}`. Las diferencias deliberadas están documentadas en [Viniendo de Shopify](/temas/viniendo-de-shopify).
## El modelo
1. La agencia escribe el tema: secciones (`sections/*.liquid`), snippets, plantillas JSON, configuración y assets. [Anatomía de un tema](/temas/anatomia-de-un-tema) describe el árbol completo.
2. Lo valida localmente (`riqra-theme check`) y lo sube (`riqra-theme push`) con el CLI, autenticada con un token de acceso.
3. La plataforma ejecuta la misma validación en el servidor, guarda los archivos e interpreta el Liquid en cada visita.
4. El comerciante personaliza el tema desde el personalizador del panel: settings globales y secciones por página. Esa personalización vive en la base de datos — una re-subida del tema nunca la pisa.
## Estados de un tema en una tienda
Una tienda puede tener varios temas instalados, con exactamente uno publicado:
| Estado | Qué significa |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **Publicado** | El tema en vivo: lo ven los compradores y es el que edita el personalizador. |
| **No publicado** | Instalado en la biblioteca de la tienda con su propia personalización guardada. Activarlo lo vuelve el publicado (intercambio atómico). |
| **Desarrollo** | Borrador temporal creado por `riqra-theme dev`, visible solo con su URL de vista previa. Expira a los 7 días. |
## Quién hace qué
| Rol | Responsabilidad |
| ----------------- | ---------------------------------------------------------------------------------------------------------------- |
| **Agencia** | Desarrolla el tema, lo valida, lo sube y lo itera con el CLI. |
| **Riqra (staff)** | Emite y revoca los tokens de acceso, prepara la tienda de desarrollo e instala el tema en la tienda del cliente. |
| **Comerciante** | Personaliza el tema instalado y lo publica. |
Subir un tema nunca cambia lo que ven los compradores: la activación es siempre un acto humano en el panel. El detalle del flujo está en [Ciclo de desarrollo](/temas/ciclo-de-desarrollo).
## Siguientes pasos
* [Primeros pasos](/temas/primeros-pasos) — instala el CLI y levanta tu primer tema.
* [Secciones y schema](/temas/secciones-y-schema) — la gramática de `{% schema %}` completa.
# Primeros pasos
Source: https://docs.riqra.com/temas/primeros-pasos
Instala el CLI, obtén tu token de acceso y levanta un tema sobre una tienda de desarrollo.
Descarga el binario `riqra-theme` para tu sistema desde los [GitHub Releases de riqra/theme-cli](https://github.com/riqra/theme-cli/releases) y colócalo en tu `PATH`.
```bash theme={null}
riqra-theme --version
```
Tu contacto en Riqra crea una tienda de desarrollo para el proyecto y emite un **token de acceso de tema** (empieza con `riqthm_`). El token queda ligado a esa tienda: define contra qué tienda trabajan `dev`, `push` y `pull`.
El secreto se muestra una sola vez al emitirse — guárdalo en un gestor de secretos. Si se pierde o se filtra, Riqra lo revoca y emite uno nuevo.
```bash theme={null}
riqra-theme login
```
Valida el token contra la API y lo guarda en `~/.riqra/credentials.json`. En CI puedes omitir `login` y exportar `RIQRA_THEME_TOKEN` en su lugar.
```text theme={null}
Logged in to https://api.riqra.com
Organization: Acme Foods
Storefront: acme.riqra.site
Token: Agencia Acme (expires never)
```
```bash theme={null}
riqra-theme init mi-tema
cd mi-tema
```
Genera un tema funcional a partir del esqueleto de Origin (el tema base de Riqra). Funciona sin conexión. Valídalo de inmediato:
```bash theme={null}
riqra-theme check
```
```bash theme={null}
riqra-theme dev
```
Sube un borrador a tu tienda de desarrollo, imprime la URL de vista previa y re-sube en cada guardado; la página de vista previa se recarga sola. Ctrl-C para salir.
## Siguientes pasos
* [Ciclo de desarrollo](/temas/ciclo-de-desarrollo) — `dev`, `push`, `riqra.theme.json` y la entrega a producción.
* [Referencia del CLI](/temas/referencia-cli) — todos los comandos y sus opciones.
# Referencia del CLI
Source: https://docs.riqra.com/temas/referencia-cli
Todos los comandos de riqra-theme y sus opciones.
```text theme={null}
riqra-theme — Riqra storefront theme CLI
Usage: riqra-theme
[options]
Commands:
login Validate and store a theme access token
logout Remove the stored token for an API URL
init Scaffold a new theme from the Origin skeleton
list List the themes uploaded by your organization
check Validate the theme locally
push Validate, zip and upload the theme
dev Watch the theme and live-push a draft preview
pull Download a theme's files from the server
```
Opciones globales: `-h, --help` (también por comando: `riqra-theme push --help`) y `-v, --version`.
## Variables de entorno
| Variable | Uso |
| ------------------- | ------------------------------------------------------------------------------ |
| `RIQRA_THEME_TOKEN` | Token de acceso (`riqthm_...`); tiene prioridad sobre el guardado. Útil en CI. |
| `RIQRA_API_URL` | URL base de la API (por defecto `https://api.riqra.com`). |
Los comandos que hablan con la API (`login`, `logout`, `list`, `push`, `dev`, `pull`) también aceptan `--api ` y `--token ` como overrides puntuales.
## login
```bash theme={null}
riqra-theme login [--token ] [--api ]
```
Valida un token de acceso contra la API y lo guarda para esa URL en `~/.riqra/credentials.json` (un token por URL de API). El token sale de `--token`, de `RIQRA_THEME_TOKEN` o de un prompt interactivo. Al validar imprime la organización, la tienda y la expiración del token.
## logout
```bash theme={null}
riqra-theme logout [--api ]
```
Elimina el token guardado para la URL de API.
## init
```bash theme={null}
riqra-theme init [name] [--path ]
```
Genera un tema nuevo a partir del esqueleto de Origin. Funciona sin conexión.
* `name` — carpeta destino (por defecto `mi-tema`); `--path` la reemplaza.
* Se niega a escribir sobre un directorio no vacío.
## list
```bash theme={null}
riqra-theme list [--json]
```
Lista los temas subidos por tu organización: slug, nombre, tipo, versión (`versionHash` corto) y fecha de actualización.
## check
```bash theme={null}
riqra-theme check [--path ] [--json]
```
Valida el árbol del tema localmente — estructura, parseo del Liquid, `{% schema %}`, JSON de plantillas y referencias cruzadas. Es la misma validación que ejecuta el servidor al subir. Sale con código 1 si hay errores; `--json` imprime los diagnósticos como JSON.
## push
```bash theme={null}
riqra-theme push [--path ] [--theme ] [--name ] [--json]
```
Valida localmente, comprime el tema y lo sube.
* El slug viene de `--theme` o de `riqra.theme.json`; un push exitoso lo guarda de vuelta ahí.
* `--name` fija el nombre visible del tema (por defecto, el slug).
* Si el servidor rechaza la subida (`422`), imprime los diagnósticos del servidor y sale con código 1.
## dev
```bash theme={null}
riqra-theme dev [--path ] [--no-open]
```
Sube una instalación en borrador y re-sube en cada guardado. La URL de vista previa renderiza el borrador y la plataforma lo recarga sola tras cada push. En macOS abre la vista previa en el navegador, salvo con `--no-open`. Ctrl-C para salir.
El tema de desarrollo y su borrador expiran a los 7 días; cada push renueva el plazo.
## pull
```bash theme={null}
riqra-theme pull [--theme ] [--path ] [--force]
```
Descarga los archivos del tema desde el servidor.
* El slug viene de `--theme` o del `riqra.theme.json` del directorio.
* No sobreescribe archivos con modificaciones locales (los lista y sale con código 1); usa `--force` para forzarlo.
# Secciones y schema
Source: https://docs.riqra.com/temas/secciones-y-schema
La gramática de {% schema %}: tipos de setting, bloques, presets, ubicaciones y settings_schema.json.
Cada sección declara su superficie editable en un bloque `{% schema %}` con JSON, al final del archivo. Es lo que el personalizador le muestra al comerciante y lo que la validación de subida verifica. Un ejemplo real de Origin:
```liquid theme={null}
{% schema %}
{
"name": "Barra de anuncios",
"enabled_on": { "groups": ["header"] },
"limit": 1,
"settings": [
{ "type": "text", "id": "message", "label": "Mensaje", "default": "" },
{ "type": "url", "id": "link", "label": "Enlace" },
{ "type": "checkbox", "id": "open_in_new_tab", "label": "Abrir en nueva pestaña", "default": false }
]
}
{% endschema %}
```
En el Liquid de la sección lees los valores con `section.settings.`; los settings globales de `settings_schema.json` con `settings.`.
## Tipos de setting
Cada setting lleva `type`, `id` y `label`, más `default`, `info` y `placeholder` opcionales. Los tipos soportados son exactamente estos (cualquier otro es un error de validación):
| Tipo | Guarda | Notas |
| -------------------- | --------------- | -------------------------------------------------------------------------------------- |
| `text` | string | Texto de una línea. |
| `textarea` | string | Texto de varias líneas. |
| `richtext` | string (HTML) | Texto enriquecido; el HTML se sanitiza en el servidor antes de llegar al drop. |
| `color` | string | Color en hex, p. ej. `#407EFF`. |
| `url` | string | URL escrita o elegida con el selector de recursos (colecciones, productos, páginas). |
| `image_picker` | string (URL) | Imagen de la biblioteca de archivos del comercio; úsala con `image_url`. |
| `number` | number | Número libre. |
| `range` | number | Número acotado con `min`, `max` y `step`. |
| `checkbox` | boolean | Casilla. |
| `select` | string | Una opción de `options: [{ "value", "label" }]`. |
| `font_picker` | string | Familia tipográfica del catálogo de fuentes. |
| `collection` | string (handle) | Referencia a una colección; resuélvela con `collections[section.settings.]`. |
| `link_list` | string (handle) | Referencia a un menú de navegación; resuélvela con `linklists[section.settings.]`. |
| `color_scheme` | string (id) | Referencia a un esquema de color del tema. Solo en secciones. |
| `color_scheme_group` | — | La lista editable de esquemas de color. Solo en `settings_schema.json`. |
| `header` | — | Encabezado no editable que agrupa settings. Lleva `content` en vez de `id`/`label`. |
```json theme={null}
{ "type": "header", "content": "Barra de contacto" },
{ "type": "checkbox", "id": "show_contact_bar", "label": "Mostrar barra de contacto", "default": true }
```
## Bloques
`blocks` declara los elementos repetibles de la sección; el comerciante los agrega, reordena y elimina. En Liquid se iteran con `section.blocks` y cada uno expone `block.type`, `block.settings` y `block.shopify_attributes` (atributos para el resaltado en el personalizador).
```json theme={null}
"blocks": [
{
"type": "slide",
"name": "Banner",
"settings": [
{ "type": "image_picker", "id": "image", "label": "Imagen" },
{ "type": "url", "id": "link", "label": "Enlace" }
]
}
]
```
```liquid theme={null}
{%- for block in section.blocks -%}
…
{%- endfor -%}
```
* `limit` en un bloque acota cuántas instancias de ese tipo se pueden agregar.
* `max_blocks` en la raíz del schema acota el total de bloques de la sección.
* `"static": true` (extensión de Riqra) marca un bloque fijo: existe exactamente una vez, se crea solo y queda anclado en el editor — el comerciante edita sus settings pero no puede quitarlo ni duplicarlo.
## Presets
`presets` define las variantes con las que la sección aparece en el panel "Agregar sección", con settings y bloques iniciales:
```json theme={null}
"presets": [
{
"name": "Carrusel de banners",
"settings": { "autoplay": true },
"blocks": [{ "type": "slide" }, { "type": "slide" }]
}
]
```
## Ubicaciones y límites
* `limit` (raíz): máximo de instancias de la sección por plantilla, p. ej. `"limit": 1` para un encabezado único.
* `enabled_on` / `disabled_on`: restringen dónde puede agregarse la sección, por plantilla (`templates: ["index", "collection", …]`) o por grupo (`groups: ["header", "footer"]`). Usa uno u otro, no ambos.
```json theme={null}
"enabled_on": { "templates": ["index", "page"] }
```
* `tag` y `class` se aceptan por compatibilidad con Shopify pero se ignoran: el framework es dueño del wrapper `riqra-section-{id}`.
## `config/settings_schema.json`
Los settings globales del tema — la pestaña "Configuración del tema" del personalizador — se declaran como un arreglo de grupos con nombre. La entrada `theme_info` es obligatoria:
```json theme={null}
[
{
"name": "theme_info",
"theme_name": "Origin",
"theme_author": "Riqra",
"color_scheme": "only light"
},
{
"name": "Tipografía",
"settings": [
{ "type": "font_picker", "id": "body_font", "label": "Fuente del cuerpo", "default": "Open Sans" }
]
}
]
```
`theme_info` acepta además `theme_version`, `theme_documentation_url` y `theme_support_url`. `color_scheme` (extensión de Riqra) declara el esquema CSS del tema: `"light"`, `"dark"`, `"light dark"`, `"dark light"` u `"only light"`.
# Viniendo de Shopify
Source: https://docs.riqra.com/temas/viniendo-de-shopify
Compatibilidad del dialecto Liquid de Riqra con Shopify: etiquetas, filtros, objetos y desviaciones deliberadas.
El dialecto Liquid de Riqra es deliberadamente literal a Shopify OS 2.0: los nombres de etiquetas, filtros, objetos y tipos de setting se conservan para que tu conocimiento de Shopify aplique 1:1. Las tablas de esta página se generan desde el registro del dialecto — la misma fuente contra la que se valida cada subida de tema — así que no pueden desviarse del runtime.
Todo el núcleo de Liquid viene incluido y no se lista aquí: control de flujo (`if`, `unless`, `case`, `for`), `assign`, `capture`, `liquid`, `echo`, `raw`, `comment`, `cycle`, `tablerow`, `increment`/`decrement`, `render`, y los filtros estándar de texto, arreglos, números, `date` y `json`.
## Etiquetas
### Soportadas
| Etiqueta |
| ------------------ |
| `{% schema %}` |
| `{% form %}` |
| `{% paginate %}` |
| `{% style %}` |
| `{% stylesheet %}` |
| `{% javascript %}` |
| `{% section %}` |
| `{% sections %}` |
### No soportadas
| Etiqueta | Alternativa |
| --------------- | -------------------------------------------------------- |
| `{% include %}` | usa `{% render %}` (aislado, como Shopify moderno) |
| `{% layout %}` | el framework es dueño del documento; no hay theme.liquid |
## Filtros
### Soportados
| Filtro |
| ------------------------------ |
| `asset_url` |
| `image_url` |
| `image_tag` |
| `stylesheet_tag` |
| `script_tag` |
| `link_to` |
| `handleize` |
| `money` |
| `money_with_currency` |
| `money_without_trailing_zeros` |
| `color_darken` |
| `color_lighten` |
| `escape` |
### No soportados
| Filtro | Alternativa |
| --------------- | ----------------------------------------------------------- |
| `t` | los temas v1 llevan textos en español inline (sin locales/) |
| `asset_img_url` | usa image\_url sobre un asset del tema |
No hay filtros de expresiones regulares. Para transformar texto usa los filtros estándar de Liquid (`replace`, `split`, `slice`, `downcase`, `handleize`, …).
## Objetos
### Soportados
| Objeto |
| ------------- |
| `shop` |
| `settings` |
| `cart` |
| `collections` |
| `linklists` |
| `request` |
| `routes` |
| `template` |
| `section` |
| `block` |
| `product` |
| `collection` |
| `search` |
| `page` |
| `paginate` |
| `breadcrumbs` |
### No soportados
| Objeto | Alternativa |
| -------------- | ---------------------------------------------------- |
| `metafields` | sin metafields en v1; usa settings del tema |
| `localization` | temas v1 en español, sin selector de idioma |
| `customer` | las páginas de cuenta son del framework, no del tema |
| `selling_plan` | sin planes de venta |
## Desviaciones de comportamiento
Diferencias deliberadas frente a Shopify que afectan cómo escribes el tema:
* **Sin `layout/theme.liquid`.** El framework es dueño del documento HTML y enlaza automáticamente `assets/theme.css` y `assets/theme.js`. Un tema es secciones + snippets + plantillas + config + assets. Ver [Anatomía de un tema](/temas/anatomia-de-un-tema).
* **Sin `locales/` ni filtro `t`.** Los textos van en español, inline en el Liquid (v1).
* **Sin versionado de temas ni migraciones.** Re-subir actualiza el tema en su lugar; un rediseño incompatible se entrega como un tema nuevo.
* **Las plantillas subidas son defaults.** La personalización del comerciante vive en la base de datos y siempre gana; una re-subida nunca la pisa (a diferencia del write-back de Shopify).
* **Wrapper y eventos propios.** Cada sección se envuelve en `` (no `shopify-section-…`). El evento de refresco de sección es `riqra:section:load` y el de cambios de carrito es `riqra:cart-changed`. Ver [Carrito AJAX y secciones](/temas/cart-ajax-y-secciones).
* **`{% paginate %}` es por cursor.** No hay páginas numeradas: el drop `paginate` expone `next` y `previous`, nada más.
* **El dinero es centavos enteros.** Todo precio en los drops (`product.price`, `cart.total_price`, …) es un entero en centavos; `| money` lo formatea con la moneda de la tienda.
* **`request.query` no está expuesto.** Reconstruye los query strings desde los drops de filtros y orden (`collection.filters[*].values[*].url`, `collection.sort_options[*].url`), que ya traen la URL correcta con la paginación reseteada.
* **Los badges de descuento se derivan.** No hay objeto de promociones en el catálogo: un producto está en oferta cuando `compare_at_price > price`.
* **`{% form %}` no acepta atributos.** Emite el `