Crear un tema
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.
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.
Por eso puedes usar el stack que quieras. Hay esqueleto para seis —Next, Astro, SvelteKit, Vue (Nuxt), React Router y Vite + React— y el contrato es el mismo en todos.
1. Empezar
npx @pcreative/theme-contract init mi-tema --name "Mi Tema" --stack astro
cd mi-tema--stack acepta next, astro, sveltekit, nuxt, react-router y
vite-react. No hace falta instalar nada antes: npx se baja la herramienta,
crea el tema y el propio tema la trae después como dependencia, así que a partir
de ahí basta con npx pcc-theme.
Eso no crea una carpeta vacía: crea un tema que ya habla con la tienda. Portada componible, catálogo paginado en servidor, ficha de producto, categoría, carrito, blog y páginas sueltas, todo contra el comercio de verdad.
Lo que no trae, para que no te pille por sorpresa:
- La página de pago. El carrito lo dice donde antes el botón apuntaba a
una página que no existía: ahora el botón vuelve al catálogo, y la nota de al
lado nombra las llamadas del contrato que resuelven una caja (
setEmail,setAddresses,listShippingOptions,setShippingMethod,listPaymentMethods,selectPaymentMethod,complete). Cuando la montes, decláralas encapabilities.pagesjunto conorder-confirmation: el esqueleto deja las dos fuera, porque declarar una página que no existe manda al instalador a un 404 y al editor a componer algo que nadie pinta. - Más de un idioma. El esqueleto sale en un solo idioma: inglés, salvo que
tu terminal esté en español (
LANG=es…), y entonces sale en español. Trae una pareja de ficheros de textos y ninguna ruta/eno/es; añadir un segundo idioma es trabajo tuyo.
Cuál elegir. Los cinco primeros renderizan en el servidor.
vite-reactes estático: el HTML llega vacío hasta que se ejecuta JavaScript, así que un buscador no ve ni una ficha de producto. Para un escaparate público es la elección equivocada; para una tienda dentro de una aplicación, tras una contraseña o en un quiosco, es perfecta.
2. Verlo funcionando
Necesitas una tienda con la que hablar, y la de verdad cabe en tu ordenador. Descarga pcreative Commerce desde pcreativecommerce.dev y arráncalo con el instalador que viene al lado del paquete:
sh instalar.sh pcreative-commerce-*.zipLo descomprime, crea .env con una contraseña aleatoria para la base de datos
y lo arranca. Si prefieres hacerlo a mano, la contraseña no es opcional: sin
POSTGRES_PASSWORD en .env la base de datos se niega a arrancar.
unzip pcreative-commerce-*.zip && cd pcreative-commerce-*/
cp .env.docker.example .env # y rellena POSTGRES_PASSWORD
docker compose up -dViene construida: no compila nada. Abre el panel en http://localhost:7001/admin, completa el asistente y deja que meta el catálogo de ejemplo. La clave publicable que necesita tu tema está aquí:
docker compose exec backend cat /app/data/clave-publicable.txtLuego, en tu tema:
cp .env.example .env.local # y pon la URL y la clave publicable
npm install
npm run devSin 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 empezar.
3. Lo que ya viene hecho
mi-tema/
theme.json quién eres y qué traes
tokens.json colores, tipos, espacios — en formato estándar (W3C DTCG)
settings.schema.json qué se puede personalizar desde el panel
settings.json los valores de fábrica
sections.schema.json qué secciones sabes pintar
templates/*.json cómo vienen compuestas tus páginas
locales/ los textos, en dos ficheros (ver abajo)
demo/contenido.json productos de ejemplo
src/ tu códigoLos idiomas van en dos ficheros y no en uno. en.json son los textos del
escaparate —los ve quien compra— y en.schema.json los del personalizador —los
ve quien lleva la tienda— (es.json y es.schema.json si el esqueleto salió en
español). Casi todo el mundo hace solo el primero, y por eso
una agencia entrega una web perfecta en francés con el panel en español.
4. Diseñar
Los colores no se escriben en el código. Van en tokens.json y llegan al
navegador como variables CSS. Un componente que escriba un #fff a pelo se
queda fuera del personalizador para siempre:
/* sí */ color: var(--color-brand-primary);
/* no */ color: #1f5f57;Lo que se puede tocar sin programar se declara en settings.schema.json. El
panel genera la pantalla solo a partir del esquema: no escribes interfaz.
Las secciones son los bloques que se recomponen desde el editor. Tu tema
declara cuáles sabe pintar en sections.schema.json, y las tres reglas de una
sección son:
- Se pinta en cualquier posición y repetida.
- Sobrevive a que le falte todo — un ajuste vacío no puede tumbar la página.
- Lleva
data-pcc-seccioncon su identificador. El esqueleto lo pone en un solo sitio a propósito, para que no se pueda olvidar en la sección número nueve. Con cualquier otro nombre de atributo se pinta perfecta y el editor no la ve.
5. Secciones con JavaScript
Cuando alguien cambia un ajuste, el editor sustituye el HTML de esa sección y deja el resto de la página en paz. Eso tiene dos consecuencias que no dan ningún error.
Los ciclos de vida de tu framework no se disparan. onMount, useEffect,
onMounted: ninguno. El HTML entra ya hecho. Hay dos eventos para eso, que
salen sobre el nodo de la sección y burbujean:
| evento | cuándo | para qué |
|---|---|---|
pcc:seccion:descargada | antes de quitar el nodo viejo | parar bucles, quitar observadores, liberar WebGL |
pcc:seccion:cargada | después de poner el nuevo | volver a montar carruseles y animaciones |
seccion.addEventListener("pcc:seccion:cargada", (e) => montar(e.detail.el))
seccion.addEventListener("pcc:seccion:descargada", (e) => limpiar(e.detail.el))🔴 Sin escuchar el de descarga, cada edición apila otro juego de escuchadores y otro bucle de animación sobre el anterior. A las diez ediciones la página se arrastra.
Y hay secciones que no se pueden pintar solas. Un héroe que fija el scroll de toda la página, un lienzo WebGL compartido o una línea de tiempo que abarca tres secciones no existen fuera de su página: sustituir su nodo no falla, deja algo pintado y roto. Se declara y el editor recarga la página para esa sección:
{ "type": "hero-cinematografico", "name": "Héroe cinematográfico", "aislable": false }Por defecto es true, que es lo que quieres en el 95 % de las secciones.
6. Hablar con la tienda
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 tiempo de ejecución en el
borde usaran el mismo código.
🔴 El dinero no se calcula en el tema. El importe y la moneda vienen dados por el comercio; tú los formateas. Un tema que multiplica precio por cantidad acaba enseñando un número creíble y equivocado en cuanto hay impuestos, descuentos o promociones por cantidad.
🔴 Ningún secreto. El tema habla con la API pública y la clave publicable,
que es pública. Pedir la base de datos, la Admin API o una pasarela hace que
validate falle.
7. Blog y páginas
Vienen puestas: templates/blog.json, blog-post.json y page.json, con sus
rutas. Las páginas sueltas —el aviso legal, los envíos, quiénes somos— las
escribe quien lleva la tienda desde su panel; tú solo las pintas.
Su contenido se pinta como HTML sin escapar, porque viene del panel de la propia tienda: quien puede escribir ahí ya puede cambiar el escaparate entero, así que no gana ningún permiso por esto. Si algún día pintas HTML de un cliente —una reseña, una pregunta— por esa misma puerta, sanéalo antes.
8. Comprobar
npx pcc-theme validate # forma y coherencia — tiene que salir SIN AVISOS
npx pcc-theme audit # qué se ejecutaría y a qué dominios habla
npx pcc-theme infoSi
auditdice «no hay fichero de bloqueo», ejecutanpm installantes. Tiene razón en pedirlo: sin él no se puede saber qué se va a descargar quien instale tu tema.
Sin avisos, no «con pocos». Un tema que se entrega con avisos enseña a ignorar los avisos, y a partir de ahí el validador no sirve para nada.
🔴 Y validar no prueba que compile. De los esqueletos de esta casa, tres
pasaban validate sin un solo aviso y no construían — y uno construía y no
arrancaba. Ejecuta
npm run build antes de entregar nada.
9. Entregar
npx pcc-theme pack
npx pcc-theme pack --key clave.pem --publisher "Tu Estudio" # firmadoUn comando, y hace las siete cosas que el .zip necesita para que el panel lo
acepte: valida, audita, busca secretos en lo que iba a empaquetar, copia a un
montaje aparte —tu carpeta no se toca—, mete los contratos dentro, instala y
construye de verdad, y escribe el archivo.
🔴 No hagas el .zip a mano. Si tus dependencias apuntan a una carpeta de tu
ordenador, el paquete instala en tu máquina y en ninguna otra — y no te enteras
hasta que alguien lo sube. pack es justo lo que arregla eso.
Solo entra lo que es parte de un tema: si tienes una carpeta propia, pack te
dice por su nombre lo que se queda fuera.
10. Si lo vendes fuera
Declara en theme.json que se vende bajo licencia:
"license_check": { "product": "mi-tema", "gracia": 7 }Quien lo compre pega su clave en el panel, en la ficha del tema. A partir de ahí:
- La comprobación va sin red. El permiso viaja firmado y se verifica con la clave pública; solo renovarlo habla con el servidor.
- La clave se usa una vez y se tira. Lo que queda guardado en la tienda es un permiso que caduca y está atado a ese dominio, no la clave de tu comprador.
- El escaparate no se apaga NUNCA por una licencia. Lo único que se niega es publicar, con el dueño delante y la tienda anterior intacta. Un servidor de licencias caído no puede dejar a oscuras a quien ya te compró.
- Comprado en el mercado de pcreative, no se pide clave: la compra ya se comprobó al descargar.
Los errores que se repiten
«0 productos» → falta la clave publicable, o apunta a otro canal de venta.
El editor no ve una sección → el atributo se llama data-pcc-seccion. Con
data-seccion se pinta perfecta y el editor no la encuentra.
La sección se pinta y está muerta → el JavaScript no se reejecuta al
sustituirla. Escucha pcc:seccion:cargada.
La página se arrastra a las diez ediciones → falta escuchar
pcc:seccion:descargada y se están apilando escuchadores.
El .zip no instala en el servidor de quien lo compró → se hizo a mano.
Usa pack.
Los colores del panel no cambian nada → hay un color escrito en el código en vez de un token.
Construye en tu portátil y muere en el servidor → next/font/google
descarga las fuentes mientras construye, y el panel construye los temas sin
red. En tu portátil ya están en caché, así que no lo ves nunca. Mete los
.woff2 dentro del tema y cárgalos con next/font/local, con la licencia al
lado. audit lo bloquea.
Y cuando esté terminado
Todo lo que viene después de «funciona» —empaquetarlo y firmarlo como es debido, publicarlo en el mercado, venderlo fuera, qué hace que te tumben la ficha y qué hacen de verdad las licencias— está en Vender el tema que has hecho.