La primera corrida completa dio 57 fallas. Solo una parte eran del
producto; el resto era instrumentación mal escrita. Queda en 261 en verde.
Defectos del producto:
- La atribución de campaña se perdía. La captura vivía en un efecto de
React, así que si la persona llegaba con parámetros de campaña y
navegaba antes de hidratar, el primer toque nunca se guardaba y
utmCampaign llegaba vacío al CRM. Ahora se captura en un script en
línea que corre al analizar el documento.
- Siete páginas sin og:image: una página que declara su propio openGraph
no hereda las imágenes del layout, las sobreescribe. Solo se nota al
compartir el enlace. Se resuelve con una función compartida en seo.ts.
- El panel no se podía usar desde Safari por HTTP: la cookie Secure no se
guarda y el acceso falla en silencio. Queda explícito y documentado.
- El panel se corría de lado en móvil: la cabecera no cabía a 375px.
- Las tarjetas de perfil del acceso se cortaban en móvil. Un elemento de
rejilla nace con min-width auto y no puede encogerse bajo su contenido.
Era además el origen de un desplazamiento que se arrastraba al tablero.
- Las tablas accesibles de las gráficas volvían desplazable la página:
sr-only fija width 1px y el algoritmo de tablas lo ignora.
- El campo de búsqueda del catálogo no tenía nombre accesible.
- Límite de tasa de 5 envíos por IP: bloqueaba una demostración en vivo
con varias personas en la misma red. Configurable, ahora 20.
- El salto de contenido pasa de left:-9999px a recorte de 1px.
Instrumentación corregida, con la razón escrita en cada caso:
- El desborde horizontal se mide intentando desplazar la página, no con
documentElement.scrollWidth, que sobreinforma con contenedores propios.
- La comprobación de accesibilidad respeta el árbol de accesibilidad.
- El aislamiento entre roles se prueba pidiendo por URL una oportunidad
ajena, no comparando folios entre listados paginados.
- Fuera las esperas por networkidle, que agotaban el tiempo sin fallar.
- Que el panel no esté enlazado se comprueba leyendo el HTML servido.
- Safari no enfoca enlaces con Tab: declarado como del navegador.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Reestructuración pedida por el cliente tras revisar la primera versión.
Conversión:
- Formulario de 14 campos a 4: nombre, correo, teléfono y mensaje. La
clasificación de riesgo ya no se pregunta, se deduce del contexto de la
página y viaja oculta. Menos fricción, misma riqueza para el análisis.
- El inicio deja de bifurcar y empuja al catálogo: 36 llamados desembocan
ahí, y las rutas por industria y escenario pasan a ser la forma de entrar
al catálogo ya filtrado, en lugar de competir como destino.
- Catálogo rehecho como tienda: barra lateral con filtros, búsqueda que
acepta expresiones regulares, títulos que abren la ficha, un solo botón
primario por tarjeta y el comparador detrás de un desplegable.
- Ficha de producto orientada al cierre: bloque en lenguaje llano sobre si
el equipo corresponde al caso, y "Cotizar este equipo" con el formulario
precargado. Se retiraron los enlaces que sacaban del embudo a leer normas.
- Todos los llamados se unifican en "Recibir cotización".
- Widget de WhatsApp: nombre, teléfono, correo y mensaje libre. El texto que
escribe la persona es el que viaja a la conversación.
Doble audiencia:
- 13 escenarios con la iconografía original de FSPM traducen un lugar
reconocible a clases de fuego y productos, para quien no domina la
terminología. La capa técnica se conserva para búsqueda.
- Héroe con fotografía en todas las landings.
Correcciones:
- El contenedor moría al arrancar porque el CLI de Prisma no podía escribir
sus motores; el chown ahora incluye /app/prisma-cli.
- Iconos repetidos entre escenarios. El set original no tiene icono de
cocina, así que ese escenario usa un marcador tipográfico explícito.
- FIREMIKS no aparecía en ningún escenario.
- Los ids de campo del formulario colisionaban con dos instancias por página.
- Se documentó el despliegue, que faltaba por completo.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>