Saltar al contenidoEasyByte

La segunda app pasó revisión porque la primera no

· · 7 min

En junio de 2026 nuestra primera app de Shopify fue rechazada en la revisión del App Store. En julio, la segunda entró en revisión en dos días, de la especificación al botón de enviar. No cambió la máquina que las construye: cambió que el rechazo de la primera lo convertimos en una regla dura con un test que hay que aprobar antes de enviar nada. Este es el postmortem de las dos, con los tres fallos exactos que tumbaron a la primera y el arnés que la segunda tuvo que pasar en verde.

Contexto: dos apps con el mismo esqueleto

Las dos apps son pequeñas y de bajo riesgo, elegidas justo por eso: para probar el proceso, no para jugarnos un producto. La primera, EasyFind, mejora el buscador de una tienda. La segunda, EasyBadge, pinta etiquetas sobre los productos ("premium", "últimas unidades") según reglas que el comerciante define en un panel. Misma familia técnica: Remix, la plantilla oficial de Shopify, un permiso de solo lectura sobre el catálogo y una theme app extension, que es el trozo de código que se cuela en la plantilla de la tienda y pinta algo en el escaparate.

Ese trozo es el que da problemas. El panel de administración lo controlamos nosotros de arriba abajo. El escaparate no: se pinta dentro del tema que el comerciante haya elegido, y hay cientos de temas, cada uno con su HTML, sus clases CSS y sus manías. Tu código entra de invitado en una casa que no has visto.

El problema: la primera la probamos solo en nuestra casa

EasyFind la verificamos contra datos de prueba en el tema por defecto. Funcionaba. La enviamos. Shopify la rechazó porque rompía en Horizon, otro de los temas base de la plataforma. Tres fallos concretos, y ninguno era un bug de nuestra lógica:

Dónde rompía en HorizonQué pasaba
El input de búsquedaSe montaba dentro de un drawer lateral, no donde lo esperábamos
Los resultadosSalían en un <dialog> en la capa superior del navegador, tapando nuestro widget
La clase .predictive-searchColisionaba con una clase del propio tema, y los estilos se pisaban

Los tres son el mismo error de fondo, y es un error de método, no de código: probamos el widget en un solo entorno y dedujimos que valía para todos. El código estaba bien. La afirmación "esto funciona" estaba mal, porque la habíamos comprobado en un sitio y la dábamos por buena en cientos.

Es la misma lección que ya nos había costado quince meses con otro producto, y que conté en saber qué no construir: construir es la parte barata. Lo que cuesta es saber si lo que construiste aguanta fuera de tu mesa. Con una app rechazada la factura fue más rápida de leer: el revisor de Shopify nos cobró en el acto lo que no habíamos verificado.

Cómo lo resolvimos: convertir el rechazo en una regla que no se salta

Lo fácil habría sido arreglar EasyFind en Horizon y seguir. Lo hicimos, pero eso no evita el siguiente rechazo: solo tapa este. Lo que hicimos además fue escribir la lección dentro del proceso que genera las apps, como regla dura:

Ninguna theme app extension llega al botón de enviar sin un arnés que la verifique, como mínimo, contra Dawn y Horizon en verde.

Dawn es el tema por defecto; Horizon, el que nos rompió. Entre los dos cubren los tres modos de fallo del rechazo. La regla no es un consejo en un documento: es una puerta. Si el arnés no está verde, la app no va al gate de envío. Punto.

El arnés es un script (e2e-badges-themes.mjs) que hace algo poco glamuroso y muy efectivo: coge el CSS y el JavaScript reales de la extensión, los inyecta en fixtures deterministas de cada tema —Dawn con su .product__title, Horizon con su caída a h1— y comprueba afirmaciones concretas, una por una:

  • que la etiqueta aparece cuando la regla casa por tag;
  • que aparece cuando casa por stock bajo;
  • que no aparece cuando no debe casar;
  • que es visible;
  • que está anclada al título del producto;
  • que nada la tapa.

Para EasyBadge, catorce comprobaciones. Catorce en verde. Y una que importa más que las otras catorce: un control negativo. Con la variable EB_HIDE_BADGES=1 forzamos que no se pinte nada, y el guard de visibilidad tiene que ponerse en rojo. Si el test pasara también con la pantalla vacía, no estaría comprobando que la etiqueta se ve: estaría comprobando que el script no revienta, que es otra cosa. Un test que pasa siempre no es un test, es un adorno. El control negativo es la diferencia entre "verificamos que funciona" y "verificamos que verificamos".

Con eso montado, EasyBadge recorrió el camino entero en dos días: especificación y construcción el 2 de julio, ficha del App Store y envío el 3. La misma máquina que construyó la primera, con una puerta nueva por la que la segunda tuvo que pasar.

Lo que salió bien y lo que todavía duele

Lo que salió bien es que la regla hizo su trabajo antes de gastar el crédito del revisor. EasyBadge no se envió con la duda de "a ver si esta vez el tema aguanta": se envió con catorce afirmaciones comprobadas y una que se pone en rojo a propósito. Eso es lo contrario de cómo mandamos la primera.

Lo que duele, en orden de cuánto:

El envío lo pulsa un humano, y así se queda. La máquina prepara la app, la despliega, la verifica y deja la ficha lista. El botón de "enviar para revisión" lo aprieto yo, y solo después de decir que sí de forma explícita. No es una limitación técnica que quiera resolver: es el gate que quiero conservar. Automatizar hasta la puerta y no cruzarla sin una persona es, para mí, la única forma sensata de dejar que una IA opere de verdad.

Hay pasos que la automatización no toca. Activar la extensión en el editor de temas exige mano humana: el editor corre en un marco aislado del navegador que no acepta clics ni tecleos sintéticos. Y hay latencias tontas —el icono de la app tarda en propagarse del panel de desarrollador a la ficha pública— que no son fallos pero parecen fallos, y te hacen dudar.

Nos pisamos a nosotros mismos. Al levantar EasyBadge con Docker, el arranque tumbó a EasyFind: los dos vivían en la misma carpeta y Docker dedujo que eran el mismo proyecto, así que trató a la primera como huérfana y la apagó. Nadie de fuera lo vio, pero fue un recordatorio de que la segunda app no vive sola: comparte servidor con la primera, y "desplegar lo nuevo" puede significar "romper lo viejo" si no lo aíslas. Lo aislamos y lo apuntamos.

Y una de higiene: en algún momento del proceso un token de Cloudflare acabó pegado en un chat. No es un incidente de seguridad —es de red interna— pero hay que rotarlo, y lo escribo aquí para no olvidarlo. La velocidad tiene estos peajes: cuando construyes rápido, dejas rastros rápido.

Lecciones para quien vaya a publicar una app en un marketplace

  1. "Funciona en mi tema" no es "funciona". Tu código de escaparate se pinta en casas que no controlas. Verifícalo al menos en dos temas distintos antes de enviar, no después del rechazo.
  2. Convierte el rechazo en regla, no en parche. Arreglar el fallo concreto solo tapa ese. Escribir la lección como puerta que hay que cruzar evita el siguiente. Un rechazo bien capitalizado vale por tres.
  3. Un test sin control negativo no verifica nada. Si tu comprobación pasa también con la pantalla vacía, no estás midiendo lo que crees. Fuerza que algo se ponga en rojo a propósito.
  4. Automatiza hasta la puerta; deja que la abra una persona. La IA puede construir, desplegar y verificar. El envío es una decisión, y las decisiones tienen dueño.
  5. La velocidad deja rastros. Construir en dos días es real y es bueno. También lo son los tokens en chats y los servicios que se pisan. Ir rápido incluye limpiar detrás.

Construir la app fue la tarde fácil. Que un revisor la aceptara fue el oficio, y el oficio esta vez estaba escrito en un test que se pone en rojo cuando debe.

Si estás a punto de publicar algo en un marketplace y no tienes claro contra qué deberías probarlo antes de darle a enviar, escríbenos a contact@easybyte.es. Te contamos qué miraríamos primero. Nos rechazaron una app para aprenderlo, así que puedes ahorrarte esa parte.

— Javier

EasyByte Hub S. Coop. Mad. — Madrid, julio 2026

Todas las guías