Toda empresa en crecimiento llega al momento en que el CRM se vuelve en contra. El pipeline de ventas no coincide con las etapas que el equipo usa de verdad, entrega pide campos que el proveedor no ofrece, finanzas exporta igual a una hoja de cálculo y la factura por puesto no deja de subir por funciones que nadie abre. Nosotros llegamos a ese momento, construimos Steppe Dev Box para sustituirlo y ahora usamos la misma base cuando un cliente pide un CRM, un back office o herramientas de operaciones. Este artículo explica la arquitectura y las concesiones con franqueza, incluido el momento en que no conviene construir el suyo.

Cuándo construir un CRM es una mala idea

Empecemos por la parte incómoda. Un CRM a medida es una mala inversión cuando:

  • Su proceso es el estándar (lead → cualificado → propuesta → ganado) y un SaaS encaja con una configuración ligera.
  • Necesita un ecosistema amplio de integraciones desde el primer día: secuencias de correo, telefonía, automatización de marketing.
  • Nadie del equipo va a ser dueño del producto después del lanzamiento. Las herramientas internas sin dueño se deterioran rápido.

Es una buena inversión cuando el proceso es la ventaja competitiva, cuando los datos tienen que quedarse en su infraestructura, cuando varios equipos necesitan vistas distintas de las mismas entidades, o cuando la factura del SaaS ya supera lo que costaría una construcción enfocada a lo largo de dos o tres años. En nuestro caso fueron el segundo y el tercer motivo: ventas, entrega y finanzas necesitaban ver proyectos, personas y dinero, cada equipo desde un ángulo distinto, y queríamos una única fuente de verdad.

La idea central: todo es un módulo

La decisión de diseño que hizo mantenible el sistema es que no hay una noción fija en el código de «lead» u «oportunidad». Hay un sistema de módulos, y un módulo es un paquete que declara:

  • un esquema de entidad: campos con tipos, validación y pistas de visualización;
  • vistas: un tablero kanban, una tabla, una página de detalle, cada una configurada y no programada;
  • relaciones con otros módulos (un proyecto pertenece a un cliente; una tarea pertenece a un proyecto);
  • permisos: quién puede leer, crear, editar y eliminar, hasta el nivel de campo;
  • hooks opcionales: funciones en el servidor que se ejecutan al crear, al actualizar o al cambiar de etapa.

El pipeline de ventas, los proyectos, los clientes, las facturas, los candidatos e incluso los activos internos son módulos. Añadir uno nuevo es escribir una definición de esquema y, si hace falta, un hook. El núcleo renderiza las vistas, aplica los permisos, persiste los datos y difunde los cambios. En la práctica, un módulo nuevo le lleva a un ingeniero alrededor de un día, y esa es la métrica que más nos importa.

Por dentro, cada módulo se mapea a un modelo de Prisma sobre PostgreSQL. Valoramos un almacén del todo dinámico y sin esquema, y lo descartamos: las tablas tipadas, las migraciones y las claves foráneas reales compensan el pequeño costo de generar una migración cuando un módulo cambia. Las columnas JSON flexibles se usan solo para atributos que de verdad son dinámicos.

Tiempo real por defecto

Un CRM que usan varias personas a la vez tiene un modo de fallo concreto: dos personas arrastran la misma tarjeta, una pierde el cambio y nadie se entera hasta que llama el cliente. Decidimos pronto que cada mutación se difunde y que cada vista abierta la refleja al momento.

El mecanismo es simple a propósito:

  1. Todas las escrituras pasan por el servidor (route handlers y server actions de Next.js), que valida contra el esquema del módulo y los permisos, escribe en PostgreSQL dentro de una transacción y devuelve el registro canónico.
  2. Tras el commit, el servidor publica un evento de cambio — { module, id, type: "created" | "updated" | "deleted", version } — en un canal.
  3. Una pasarela WebSocket reparte los eventos a los clientes conectados, filtrados por lo que cada cliente tiene permiso de ver.
  4. El cliente mantiene una caché normalizada por módulo. Ante un evento, actualiza el registro en el sitio o, si la versión indica que se perdió algo, vuelve a pedir ese registro.

El arrastrar y soltar usa actualizaciones optimistas con reversión: la tarjeta se mueve al momento, el servidor confirma o rechaza, y un rechazo la devuelve a su sitio con un mensaje. Los conflictos se resuelven con números de versión — una escritura desactualizada se rechaza y el cliente refresca los datos — y con eso ha bastado para un equipo de nuestro tamaño. La edición colaborativa de verdad, en campos de texto largos, necesitaría CRDT; no la hemos necesitado.

La interfaz: rápida para el uso diario

Las herramientas internas se usan durante horas al día, así que la rapidez de la interacción importa más que el adorno visual. Los patrones que se ganaron su lugar:

  • Pipelines kanban con arrastrar y soltar, como vista principal de todo lo que tiene etapas, con la misma vista de tabla para las operaciones masivas.
  • Edición en línea en tablas y páginas de detalle — clic en una celda, se cambia, tabulador a la siguiente — con la validación del esquema del módulo.
  • Navegación por teclado y una paleta de comandos para saltar entre registros y ejecutar acciones.
  • Filtros y vistas guardados por usuario, para que cada rol llegue a la porción de datos que necesita.
  • Renderizado en servidor en la primera carga y, después, navegación en el cliente con datos en caché, lo que mantiene la aplicación usable incluso con una conexión lenta.

Usamos Next.js y TypeScript en todo el stack, con Tailwind CSS para los estilos. Los tipos compartidos entre el esquema de Prisma, el servidor y el cliente explican en gran parte por qué el sistema de módulos se puede ampliar rápido y con seguridad.

Permisos hasta el campo

Los roles de un CRM rara vez son nítidos. Un comercial debe ver el importe de las oportunidades, pero no los salarios; un contratista debe ver sus tareas, pero no el presupuesto del cliente. Implementamos permisos en tres niveles — módulo, registro y campo — y el servidor los evalúa en cada lectura y en cada escritura. Las vistas se generan a partir de los campos permitidos, de modo que un usuario no ve una columna que no puede leer, y la pasarela WebSocket aplica las mismas reglas antes de difundir, de modo que un campo prohibido no viaja por la red.

Es más trabajo que una división simple entre administrador y usuario. También es la función que nos permitió abrir el sistema a socios y contratistas sin construir un portal aparte.

Cuánto cuesta operarlo

Las cifras que nos suelen pedir:

  • Infraestructura: una instancia gestionada de PostgreSQL, un proceso pequeño de Node.js para la pasarela WebSocket y la aplicación Next.js en Vercel. Para una empresa de nuestro tamaño, la factura mensual es comparable a un puñado de puestos de SaaS.
  • Mantenimiento: unas pocas horas al mes para actualizaciones de dependencias y cambios pequeños de esquema. Los módulos nuevos son el trabajo continuo principal, y los mueve la necesidad del negocio, no el mantenimiento.
  • Construcción inicial: un sistema con el núcleo de módulos, sincronización en tiempo real, tres o cuatro módulos y permisos es un proyecto de 6–10 semanas para un equipo reducido. Compárelo con el costo a tres años de un SaaS, según su número de puestos, antes de decidir.

Reutilizar la base con clientes

Como el sistema de módulos es genérico, Steppe Dev Box pasó a ser un punto de partida para proyectos de clientes, en lugar de un desarrollo de una sola vez: back offices de marketplaces, portales de socios, paneles de operaciones. El núcleo — módulos, vistas, permisos, sincronización en tiempo real — se queda; los módulos se adaptan al proceso del cliente. Ese es también el consejo franco si está valorando un CRM a medida: no construya un CRM, construya un sistema de módulos y después describa su CRM dentro de él.