Ir al contenido

Crear un tema desde cero

Un tema es una aplicación web independiente. No corre dentro de la tienda: habla con ella por HTTP, como lo haría cualquier cliente.

Eso significa que puedes usar el stack que quieras — Next, Astro, Vite, Nuxt, SvelteKit, Remix— siempre que cumplas el contrato.

Una carpeta dentro de themes/ con esto:

mi-tema/
theme.json ← obligatorio: quién eres y qué traes
settings.schema.json ← qué se puede personalizar desde el panel
sections.schema.json ← qué bloques se pueden recomponer (opcional)
demo/contenido.json ← contenido de ejemplo (opcional, muy recomendable)
.env.example ← qué variables necesitas

Sin theme.json el panel no lo ve.

Declara qué eres y qué sabes hacer:

{
"contract": "2.0",
"id": "mi-tema",
"name": "Mi Tema",
"version": "1.0.0",
"runtime": {
"stack": "next",
"commands": { "install": "npm install", "dev": "npm run dev", "build": "npm run build" },
"env": [
{ "name": "NEXT_PUBLIC_PCC_BACKEND_URL", "required": true },
{ "name": "NEXT_PUBLIC_PCC_PUBLISHABLE_KEY", "required": true }
]
},
"capabilities": {
"pages": ["home", "catalog", "product", "cart", "checkout", "order-confirmation"],
"blocks": ["hero", "bestsellers", "newsletter"],
"locales": ["es"]
}
}

capabilities.pages no es decorativo: el panel avisa si dices que tienes checkout y no declaras página de confirmación de pedido. Un cliente que paga y no aterriza en ninguna parte es un carrito perdido.

La lista completa de campos está en el contrato de tema.

Dos datos, y el segundo es el que más se olvida:

Terminal window
COMMERCE_URL=https://mitienda.com
COMMERCE_KEY=pk_...

Sin la clave publicable tu tema arranca y no ve ni un producto, y el error no dice que falte una clave. Es el fallo número uno al montar un tema.

Puedes hablar con la Store API a pelo con fetch, o usar el adaptador del contrato de datos:

import { createCommerce } from "@pcreative/commerce-contract/api"
const commerce = createCommerce({
baseUrl: process.env.COMMERCE_URL,
publishableKey: process.env.COMMERCE_KEY,
countryCode: "es",
})

El adaptador usa fetch a secas, sin ningún SDK: un SDK presupone navegador, y eso es justo lo que impediría que un tema Astro o un runtime edge usaran el mismo código.

Un tema vacío no se puede juzgar. Pon un demo/contenido.json con categorías y productos:

{
"categorias": [{ "handle": "tartas", "nombre": "Tartas" }],
"productos": [{
"handle": "tarta-chocolate",
"titulo": "Tarta de chocolate",
"categoria": "tartas",
"imagenes": ["https://…"],
"variantes": [{ "titulo": "8 raciones", "precio": 28, "sku": "TC-8" }]
}]
}

Es agnóstico de la plataforma: describe productos, no tablas de nadie. El panel lo valida antes de importar y te dice qué trae.

En settings.schema.json declaras qué se puede tocar sin programar: colores, tipografías, textos, imágenes. El panel genera la pantalla sola a partir del esquema — no tienes que escribir interfaz.

«0 productos» → falta la clave publicable, o apunta a otro canal de venta.

CORS bloqueando todo → tu dirección no está en STORE_CORS del backend. Cuando montes el tema en un puerto nuevo, acuérdate.

Precios a NaN → la Store API devuelve unit_price y currency_code; si tu interfaz lee price y currency, falta el mapeo. Es silencioso.

El checkout no crea el pedido → falta algún paso. El contrato exige, por este orden: setEmail, setAddresses, setShippingMethod (uno por paquete si hay marketplace), selectPaymentMethod y complete. Cada uno devuelve el carrito actualizado; el que falle te dice qué falta.