Uriel JarethandClaude Opus 5 0e0331c1fc feat: catálogo como centro del embudo y captura de baja fricción
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]>
2026-08-28 01:30:44 -06:00

FSPM — sitio comercial y micro CRM

Demostración construida por Consultoría E3 para Fire Service Plus México. Sitio público orientado a venta consultiva, con un CRM interno que registra cada envío de formulario y de widget de WhatsApp como oportunidad, con su atribución de campaña.

No es un maquetado: los formularios escriben en base de datos, el panel lee de ella, y las reglas de asignación reparten los leads entre vendedores.

De dónde salió el contenido

El sitio implementa las recomendaciones de una auditoría de marca y mercado previa. Los hallazgos que dirigieron el diseño:

Hallazgo de la auditoría Cómo se resuelve aquí
Propuesta demasiado amplia, ocho categorías sin rutas Inicio con tres rutas —industria, riesgo y cumplimiento— y cinco páginas por segmento prioritario
El visitante debe inferir qué solución le toca Clasificador de riesgo en el héroe: elige operación y clases de fuego, y el sitio lo enruta
Claims sin condiciones ni evidencia por modelo Aislados en claimsPorVerificar y presentados como compromiso de documentación, nunca como característica
Sin meta description ni Open Graph Metadatos por página, sitemap derivado de los datos, JSON-LD y tarjeta social generada
Conversión poco consultiva El formulario pide lo que un ingeniero necesita para cotizar, no "solicita información"
Sin forma de medir efectividad comercial Atribución de primer toque que sobrevive a la navegación, y analítica por campaña en el panel

Los datos de producto provienen de la extracción del sitio público de FSPM. Lo que la fuente no sostiene está marcado como pendiente de verificar; nada se inventó para rellenar.

Stack

Next.js 15 App Router · React 19 · TypeScript estricto · Tailwind CSS v4 · Prisma 6 + SQLite · sesiones propias con jose · Playwright para pruebas. Sin librería de gráficas: el tablero dibuja SVG a mano.

Arrancar en local

npm install
cp .env.example .env          # ajusta AUTH_SECRET
npx prisma db push
npm run db:seed               # datos de demostración
npm run dev

Sitio en http://localhost:3000. El panel en /admin/login — no está enlazado desde el sitio público, es intencional.

Las credenciales del seed se imprimen al final de npm run db:seed. En la pantalla de acceso hay además entrada rápida por perfil para la demostración, que se apaga con DEMO_ACCESO_RAPIDO=false.

Estructura

src/app/(sitio)/     páginas públicas
src/app/admin/       panel comercial, con noindex y fuera del sitemap
src/app/api/leads/   captura: deduplica contacto, crea oportunidad, asigna
src/data/            catálogo, industrias, clases de fuego, datos de empresa
src/lib/crm/         dominio, sesiones, consultas, acciones, asignación
src/components/marca/RielClases.tsx    el elemento firma del diseño
tests/               Playwright, incluidos dos proyectos WebKit
docs/CONTRATO.md     sistema de diseño y reglas de contenido
docs/DESPLIEGUE.md   variables, Docker y despliegue

Cómo funciona la captura

  1. El visitante llega con parámetros de campaña. src/lib/utm.ts guarda el primer toque y no lo sobreescribe.
  2. Navega. Envía el formulario en una ficha de producto, ya sin parámetros en la URL.
  3. POST /api/leads deduplica el contacto por correo o teléfono normalizado, crea una oportunidad nueva —un mismo contacto acumula varias— y guarda la campaña del primer toque junto con el producto y la URL exactos.
  4. Las reglas de asignación eligen vendedor; si ninguna coincide, se reparte por turno entre los activos.
  5. El widget de WhatsApp hace lo mismo antes de abrir la conversación, así el lead existe aunque la persona nunca mande el mensaje.

Pruebas

npm run test:e2e        # todos los proyectos
npm run test:webkit     # solo Safari e iOS

Cubren rutas y metadatos, responsividad de 320 a 1440 sin desborde horizontal, el circuito de captura con atribución, el aislamiento entre roles del panel y accesibilidad básica.

Alcance

Los datos del panel son ficticios. Los logotipos de clientes se muestran sin atribuirles testimonio ni resultado: la auditoría pide confirmar la relación antes de usarlos comercialmente. La información normativa es de referencia y no sustituye dictamen técnico ni jurídico.

S
Description
No description provided
Readme
2.6 MiB
Languages
TypeScript 97.4%
CSS 1.2%
Dockerfile 0.8%
Shell 0.3%
JavaScript 0.3%