Ir al contenido

Levantar pcreative Commerce en local

Tres procesos y una base de datos. En una máquina limpia, de cero a tienda navegable en unos minutos.

apps/backend la tienda (backend) :9000
apps/admin panel :7001/admin
themes/growshop-premium escaparate :3000

Terminal window
docker compose up -d # Postgres :5434 (y un Redis que solo usa el camino viejo)

El puerto no es el de serie (5432) a propósito: así puedes tener varias tiendas levantadas a la vez sin que se pisen.

Terminal window
npm ci # desde la RAÍZ: es un monorepo con workspaces. `ci`, no `install`

npm install reescribe el lockfile y recoloca el árbol entero; npm ci instala exactamente lo probado.

Terminal window
cp apps/backend/.env.example apps/backend/.env
# ajusta DATABASE_URL al puerto del docker-compose
cd apps/backend
npm run preparar # crea el esquema (base vacía) o migra, y prepara la tienda
npm run pcc -- rescate alta admin@ejemplo.com # el primer acceso al panel: enseña la contraseña
npm run dev # :9000, recargando al guardar

preparar decide solo si instala o migra, y deja la fila de tienda, el canal de venta y la clave publicable que el escaparate necesita. rescate alta crea un administrador entero —usuario, identidad y contraseña, en una transacción— desde la consola, y enseña la contraseña generada una sola vez. También sirve el asistente del navegador, que es lo que ve quien instala de verdad.

Con contenido de ejemplo:

Terminal window
npm run seed # 6 categorías y 24 productos de demostración (usa el motor viejo)

El seed hace dos cosas que no son cosméticas:

  • Retira pp_system_default de la región y activa los proveedores reales. Ese proveedor es el de pruebas: cobra 0 € y da el pedido por pagado. Es el fallo más silencioso de una instalación nueva, porque la tienda «funciona».
  • Pone precios distintos a los dos métodos de envío, que de serie vienen los dos a 10 €.

Sin SMTP_HOST el sistema arranca igual: los emails se escriben en el log en lugar de enviarse. Configurar el correo es un paso de puesta en marcha, no un requisito para levantar el backend.

Terminal window
cp themes/growshop-premium/.env.example themes/growshop-premium/.env.local

NEXT_PUBLIC_COMMERCE_KEY es la clave publicable del canal de venta. Si no la tienes a mano:

Terminal window
docker exec pcc-db psql -U "$POSTGRES_USER" -d pcreative_commerce # el usuario que pusieras en docker-compose.yml \
-tAc "select token from api_key where type='publishable' limit 1"
Terminal window
npm run dev:theme # :3000
Terminal window
npm run dev:admin # :7001/admin

En Temas aparece cada carpeta de themes/ que tenga un theme.json válido. Al entrar en uno, el formulario del customizer se genera a partir de su settings.schema.json: el panel no sabe qué ajustes tiene un tema hasta que lo lee, y por eso vale igual para un tema Next que para uno Astro o PHP.

Guardar escribe themes/<id>/theme.override.json. En desarrollo el storefront relee el tema en cada petición, así que el cambio se ve al recargar — incluidas las escalas de color derivadas, que se recalculan solas.


Puede que estés viendo un panel con secciones que no están en este repo. Es a propósito: una tienda puede añadir las suyas —integraciones con sus proveedores, informes a medida— y esas viven en su propia instalación, no en el producto.

El panel las descubre solas: el backend anuncia lo suyo en GET /admin/capabilities y el menú las añade. Sin ese endpoint el panel funciona igual y sin errores.

Terminal window
npm test # contratos: 33 tests, sin backend
npm run theme -- validate themes/growshop-premium
npm run theme -- info themes/growshop-premium
npm run theme -- css themes/growshop-premium # las variables ya resueltas

React se fija en la raíz. react y react-dom están en las devDependencies del package.json raíz aposta. Una dependencia del camino viejo arrastra React 18 (un panel que tenemos desactivado) y npm lo subía a la raíz, donde también vive el next del tema: el tema acababa con dos Reacts y el build moría con el error minificado #31 («objeto con claves {$$typeof, type…}»), que no dice nada de la causa. Fijar React 19 en la raíz deja una sola copia.

No hace falta —y conviene evitar— aliasar react en next.config: eso se salta las condiciones de exportación react-server y rompe la capa de Server Components con un Cannot read properties of null (reading 'useOptimistic').

Leer el carrito no es una acción de servidor. carritoActual() vive en lib/cart-read.ts y no en lib/cart.ts. Un módulo con "use server" convierte todas sus exportaciones en acciones, y llamar a una acción durante el render no marca la página como dinámica: Next intentaba prerenderizar /carrito en el build y fallaba. Las mutaciones van en cart.ts; las lecturas, fuera.