El proyecto del curso de 40 horas
NexoCRM: El CRM sencillo para que un pequeño negocio de servicios no pierda ninguna oportunidad.
Una única aplicación web, rápida y usable desde el móvil, donde el equipo de un pequeño negocio de servicios registra cada contacto, empresa, oportunidad y tarea, ve en qué punto está cada venta y sabe qué seguimiento toca hoy. Está construida con Next.js y Supabase, protegida con RLS por workspace y publicada en Vercel, de forma que quien la crea puede seguir mejorándola durante meses con Claude Code o Codex sin depender de nadie.
- Requisitos funcionales
- 13
- Con criterios de aceptación verificables.
- Tablas con RLS
- 9
- Aisladas por workspace desde el primer día.
- Pantallas
- 18
- Tres públicas y el resto tras la sesión.
- Hitos con evidencia
- 5
- Cada uno deja entregables registrados.
El encargo
Qué problema resuelve y para quién
El proyecto no arranca con código: arranca sabiendo qué se rompe hoy en el negocio y quién lo sufre.
Propietario/a (owner)
Dirige el negocio y también vende. Necesita ver el estado real de las oportunidades sin perseguir a nadie y decidir dónde poner el esfuerzo comercial esta semana. Es quien crea el workspace y gestiona al equipo.
- Ver en menos de un minuto cuántas oportunidades hay abiertas, su valor ponderado y qué tareas están atrasadas.
- Crear el workspace, dar acceso a su equipo y confiar en que solo ellos ven los datos.
- Registrar una oportunidad con importe, probabilidad y fecha esperada, y moverla de etapa sin perder el historial.
- Cerrar una oportunidad como ganada o perdida con motivo y ver cómo cambia el dashboard.
Miembro del equipo (member)
Atiende clientes y hace el seguimiento diario. Necesita saber qué le toca hoy y dejar constancia de cada llamada o nota para que el resto del equipo no repita trabajo ni contradiga lo ya dicho.
- Encontrar un contacto por nombre, correo o teléfono en segundos y ver su empresa, oportunidades y últimas notas.
- Completar las tareas de hoy, ver las atrasadas y crear la siguiente acción sin salir de la ficha.
- Anotar el resultado de una llamada o reunión en el timeline del contacto o de la oportunidad.
Alcance
Qué entra en el proyecto y qué queda fuera
Definir el límite es parte del trabajo: un alcance cerrado es lo que permite terminar y publicar.
Entra en el alcance
13 funciones- Registro, inicio y cierre de sesión, recuperación de contraseña y rutas protegidas.
- Creación automática del workspace inicial con su propietario/a y las etapas de pipeline por defecto.
- Dashboard con KPIs, pipeline resumido, tareas urgentes y próximos seguimientos.
- Empresas: listado, búsqueda, alta, edición, detalle y contactos relacionados.
- Contactos: listado, búsqueda, filtros, alta, edición, detalle y empresa relacionada.
- Oportunidades: CRUD con empresa y contacto, importe, probabilidad, fecha esperada, etapa, ganada o perdida y actividad registrada.
- Pipeline por columnas con alternativa de lista accesible y cambios de etapa persistidos.
- Tareas con prioridad, fecha límite, estado, filtros pendientes / hoy / atrasadas y relación opcional con contacto u oportunidad.
- Notas y actividades: timeline en contacto y oportunidad con eventos automáticos y notas manuales.
- Búsqueda global en contactos, empresas y oportunidades.
- Estados de carga, vacío, error y éxito cuidados en cada flujo relevante.
- Diseño responsive, usable en móvil y con teclado.
- Datos demo ficticios para enseñar la aplicación sin información real.
Queda fuera
7 exclusiones- Facturación, presupuestos en PDF o cobros.
- Email marketing, envíos masivos o automatizaciones de correo.
- Integraciones externas (WhatsApp, Gmail, calendarios, Zapier o similares).
- Aplicación nativa iOS o Android; la web responsive cubre el uso en móvil.
- IA predictiva: puntuación automática de leads o previsión de cierre.
- Multi-idioma; toda la interfaz está en español.
- Permisos granulares por campo o por registro; solo existen los roles owner y member.
Demo segura
Recorre las pantallas con datos ficticios
Esta maqueta reproduce el panel, el listado de contactos y el pipeline de NexoCRM. Los nombres, empresas e importes están inventados: no hay datos reales de ninguna persona.
- Oportunidades abiertas
- 18
- 6 en negociación
- Valor ponderado
- 34.150 €
- Importe por probabilidad
- Ganadas este mes
- 5
- 21.900 € cerrados
- Tareas atrasadas
- 3
- Revisar hoy
Importe abierto por etapa
- Nuevo9800 €6 oportunidades
- Cualificado14.200 €5 oportunidades
- Propuesta18.600 €4 oportunidades
- Negociación12.400 €3 oportunidades
- Ganado21.900 €5 oportunidades
| Categoría | Valor |
|---|---|
| Nuevo | 9800 € |
| Cualificado | 14.200 € |
| Propuesta | 18.600 € |
| Negociación | 12.400 € |
| Ganado | 21.900 € |
Tareas que reclaman atención
Llamar para confirmar la propuesta
Estudio Malva
Prioridad altaVencía ayerEnviar presupuesto revisado
Clínica Duero
Prioridad altaHoyPreparar visita de seguimiento
Talleres Bracamonte
Prioridad mediaEn 3 días
| Categoría | Valor | Porcentaje |
|---|---|---|
| Cualificado | 2 contactos | 40 % |
| Cliente | 1 contacto | 20 % |
| Lead | 1 contacto | 20 % |
| Inactivo | 1 contacto | 20 % |
| Contacto | Empresa | Estado | Próximo seguimiento |
|---|---|---|---|
| Marta Ferrán | Estudio Malva | Cualificado | Mañana |
| Julián Ortiz | Talleres Bracamonte | Cliente | En 5 días |
| Noelia Prats | Academia Sierra Norte | Lead | Hoy |
| Óscar Benhamou | Clínica Duero | Cualificado | En 2 días |
| Rocío Vilaplana | Vilaplana Consultoría | Inactivo | Sin seguimiento |
Nuevo
6 oportunidades · 9.800 €
Cualificado
5 oportunidades · 14.200 €
Programa de formación
Academia Sierra Norte
3.200 € · 30 % · 2 abr
Propuesta
4 oportunidades · 18.600 €
Rediseño de marca
Estudio Malva
6.500 € · 60 % · 18 mar
Auditoría de procesos
Clínica Duero
7.400 € · 50 % · 9 abr
Negociación
3 oportunidades · 12.400 €
Mantenimiento anual
Talleres Bracamonte
4.800 € · 80 % · 24 mar
Ganado
5 oportunidades · 21.900 €
El tablero se desplaza en horizontal dentro de su propio contenedor y tiene una vista de lista equivalente para quien navega con teclado o lector de pantalla.
La demo funciona con datos ficticios cargados en el navegador: puedes crear, editar y borrar sin afectar a nadie.
Requisitos funcionales
13 requisitos repartidos por área
Cada requisito tiene criterios de aceptación verificables: así sabes cuándo está hecho de verdad. Despliega el área que te interese.
- Requisitos funcionales
- 13
- De RF-01 a RF-13, todos obligatorios.
- Áreas de producto
- 13
- De la autenticación a los datos de demostración.
- Criterios de aceptación
- 60
- Cada uno se comprueba usando la aplicación o un comando.
RF-01 Registro, acceso, cierre de sesión, recuperación y rutas protegidas
Cualquier persona puede crear una cuenta con correo y contraseña, entrar, salir y recuperar la contraseña. Todas las rutas de la aplicación exigen sesión; las públicas son solo /login, /register y /forgot-password.
Criterios de aceptación (5)
- Una persona se registra en /register con correo y contraseña y, tras confirmar el correo, inicia sesión en /login y llega a /dashboard.
- Al cerrar sesión la sesión queda invalidada y cualquier ruta privada redirige a /login.
- Desde /forgot-password se envía el correo de recuperación de Supabase y el mensaje de éxito no revela si el correo existe.
- Sin sesión, acceder a /dashboard, /contacts, /companies, /deals, /pipeline, /tasks o /settings redirige a /login conservando la ruta de destino en ?next=.
- Los errores de credenciales se muestran en el formulario de forma anunciable (role alert) y sin exponer detalles técnicos.
RF-02 Creación del workspace inicial y gestión básica de miembros
Al entrar por primera vez, la aplicación crea el workspace de la persona con su membresía como owner y las etapas de pipeline por defecto. Los ajustes permiten renombrar el workspace y ver o gestionar miembros según el rol.
Criterios de aceptación (4)
- En el primer acceso sin membresía la aplicación llama a create_workspace_with_owner con el nombre del negocio (propone "Mi negocio"), y esa función crea en una sola transacción el workspace, la fila owner en workspace_members y las seis etapas: Nuevo, Cualificado, Propuesta, Negociación, Ganado y Perdido. La aplicación no inserta directamente en esas tres tablas: las políticas RLS se lo impiden.
- La fila de profiles se crea automáticamente al registrar el usuario (trigger sobre auth.users) con full_name.
- En /settings/workspace la persona owner cambia el nombre del workspace; una member lo ve pero el formulario está deshabilitado.
- En /settings/members se listan los miembros con su rol; solo owner puede añadir por correo de un usuario registrado o quitar miembros, y no puede quitarse a sí mismo.
RF-03 Dashboard con KPIs, pipeline resumido, tareas urgentes y próximos seguimientos
La pantalla de inicio responde a las cinco preguntas del negocio con datos del workspace actual y enlaza a la acción siguiente en cada bloque.
Criterios de aceptación (5)
- Muestra cinco tarjetas: oportunidades activas (etapas con is_closed = false), valor ponderado (suma de importe × probabilidad / 100 de las activas), ventas ganadas del mes (importe de las oportunidades en etapa is_won cuyo updated_at cae en el mes en curso), tareas vencidas (abiertas con due_date anterior a hoy) y próximos seguimientos (tareas abiertas con due_date entre hoy y hoy + 7 días).
- Cada KPI se calcula solo con datos del workspace actual, en la función pura computeKpis({ stages, deals, tasks, today }) de lib/kpis.ts, y coincide con los valores conocidos del seed de demo que usan los tests.
- Incluye pipeline resumido (número e importe por etapa), lista de tareas urgentes y próximos seguimientos, y cada bloque enlaza a la acción siguiente: /tasks?view=overdue, /tasks?view=upcoming, /deals?status=won y /pipeline.
- Con un workspace sin datos muestra un estado vacío con la acción de crear el primer contacto.
- Se lee completo a 360 px de ancho sin desplazamiento horizontal.
RF-04 Empresas: listado, búsqueda, alta, edición, detalle y contactos relacionados
Las empresas agrupan contactos y oportunidades. Se gestionan desde /companies con listado, búsqueda, formulario y ficha de detalle.
Criterios de aceptación (4)
- /companies lista las empresas del workspace con búsqueda por nombre y sector, ordenadas por actualización más reciente.
- /companies/new crea una empresa validando nombre obligatorio y web con formato URL; los errores aparecen junto al campo correspondiente.
- /companies/[id] muestra los datos, los contactos relacionados, las oportunidades abiertas y la actividad reciente, y permite editar.
- Al guardar aparece una confirmación accesible y el listado refleja el cambio sin recargar la página a mano.
RF-05 Contactos: listado, búsqueda, filtros, alta, edición, detalle y empresa relacionada
Los contactos son el centro del CRM. Se gestionan desde /contacts con búsqueda, filtros combinables, formulario validado y ficha con toda su información relacionada.
Criterios de aceptación (5)
- /contacts busca por nombre, correo y teléfono con debounce de unos 300 ms y filtra por estado y empresa de forma combinable; los filtros se reflejan en la URL.
- /contacts/new y la edición validan con Zod: nombre obligatorio, correo con formato válido, teléfono opcional y empresa opcional del mismo workspace.
- El formulario guarda estado, fuente y fecha del siguiente seguimiento.
- /contacts/[id] muestra la ficha, la empresa enlazada, sus oportunidades, sus tareas y el timeline de actividad.
- El listado tiene estado de carga (skeleton), vacío (con acción de crear) y error (con reintento).
RF-06 Oportunidades: CRUD, relaciones, importe, probabilidad, fecha, etapa, cierre y actividad
Cada venta potencial se registra como oportunidad con su valor esperado, su etapa y su relación con empresa y contacto. Todo cambio relevante deja rastro en el timeline.
Criterios de aceptación (5)
- CRUD completo desde /deals, /deals/new y /deals/[id], con relación opcional a una empresa y un contacto del mismo workspace.
- Validación: título obligatorio, importe mayor o igual que 0, probabilidad entre 0 y 100, fecha esperada de cierre opcional y etapa existente en el workspace.
- Marcar como ganada mueve la oportunidad a la etapa con is_won; marcar como perdida exige lost_reason y la mueve a la etapa cerrada no ganada. No hay columna de fecha de cierre: la marca de tiempo es updated_at.
- Cada creación, cambio de etapa y cierre inserta una fila en activities con su type (deal_created, stage_change, deal_won o deal_lost) y su metadata; en un cambio de etapa, {"from": "Propuesta", "to": "Negociación"}.
- El detalle muestra el valor ponderado (importe × probabilidad / 100) y el timeline de la oportunidad.
RF-07 Pipeline por columnas con alternativa de lista accesible y cambios de etapa persistidos
El pipeline muestra las oportunidades abiertas por etapa y permite moverlas sin perder accesibilidad. El arrastre, si existe, es un complemento.
Criterios de aceptación (5)
- /pipeline muestra una columna por etapa ordenada por position, con recuento e importe total en la cabecera de cada columna.
- Existe una vista de lista alternativa (tabla) y un conmutador entre ambas que se recuerda durante la sesión.
- El cambio de etapa se hace desde un selector o menú accesible por teclado en la tarjeta y en la lista; si hay arrastre, nunca es la única vía.
- El cambio de etapa persiste en deals.stage_id y genera una actividad automática de tipo stage_change.
- Tras mover una oportunidad, las columnas de origen y destino se actualizan sin recargar y el cambio sigue ahí al refrescar.
RF-08 Tareas: crear, editar, completar, prioridades, fechas, filtros y relación opcional
Las tareas convierten el CRM en una herramienta de seguimiento diario: qué toca hoy, qué está atrasado y a qué contacto u oportunidad pertenece cada acción.
Criterios de aceptación (5)
- /tasks permite crear, editar, completar y reabrir tareas con título, descripción, fecha límite, prioridad (baja, media, alta), estado y responsable.
- Las vistas se reflejan en la URL con ?view= y son correctas según due_date y status, calculadas con la fecha local: pending (por defecto), today, overdue, upcoming, done y all. Una tarea abierta es la que está en pending o in_progress; cancelled nunca cuenta como pendiente.
- Una tarea se enlaza opcionalmente a un contacto o a una oportunidad y desde ella se navega a la ficha relacionada.
- Completar una tarea guarda completed_at y crea una actividad task_completed en el timeline relacionado.
- Las tareas atrasadas se distinguen con icono y texto, no solo con color.
RF-09 Notas y actividades: timeline con eventos automáticos y notas manuales
Contactos y oportunidades tienen un historial cronológico que combina lo que la aplicación registra sola con lo que el equipo anota a mano.
Criterios de aceptación (4)
- En /contacts/[id] y /deals/[id] hay un timeline ordenado de más reciente a más antiguo con eventos automáticos y notas manuales.
- Tipos soportados, los doce del modelo: note, call, email, meeting, stage_change, task_created, task_completed, deal_created, deal_won, deal_lost, contact_created y company_created. Los cuatro primeros son notas manuales; el resto los crea la aplicación.
- Se puede añadir una nota manual con texto obligatorio; aparece al instante en el timeline y guarda actor_id.
- Cada evento muestra tipo, fecha relativa y autor/a; los automáticos muestran su metadata de forma legible (por ejemplo, etapa de origen y destino).
RF-10 Búsqueda global en contactos, empresas y oportunidades
Desde cualquier pantalla se puede buscar un registro y saltar a su detalle sin pasar por los listados.
Criterios de aceptación (4)
- Un buscador global accesible desde el shell (botón visible y atajo Ctrl/Cmd+K) busca en contactos, empresas y oportunidades del workspace.
- Los resultados se agrupan por tipo, muestran como máximo 5 por grupo y se recorren con flechas y Enter.
- Sin resultados se muestra un mensaje útil con accesos para crear un contacto, una empresa o una oportunidad.
- La búsqueda se lanza a partir de 2 caracteres y usa debounce para no saturar Supabase.
RF-11 Estados de carga, vacío, error y éxito de calidad en cada flujo
Ninguna pantalla se queda en blanco ni muestra un error técnico. Cada listado, detalle y formulario comunica qué está pasando y qué hacer a continuación.
Criterios de aceptación (4)
- Cada listado y detalle tiene componente de carga (skeleton), vacío (mensaje y acción), error (mensaje y reintento) y éxito (toast o mensaje en línea).
- Los mensajes de error explican qué hacer y no muestran trazas ni textos técnicos de Supabase.
- Los toasts son accesibles: usan role status o alert, se cierran solos y no bloquean la navegación.
- Los formularios deshabilitan el botón de envío mientras guardan y evitan el doble envío.
RF-12 Diseño responsive y usable en móvil y con teclado
La aplicación se usa desde el móvil del equipo comercial y con teclado en escritorio. El shell se diseña así desde el módulo 3 y se verifica en el QA final del módulo 9.
Criterios de aceptación (5)
- Todas las rutas se usan sin desplazamiento horizontal a 360 px, 768 px y 1280 px de ancho.
- La navegación principal se convierte en menú compacto en móvil y mantiene foco visible y orden de tabulación correcto.
- Las tablas anchas se muestran como tarjetas o con desplazamiento propio en móvil.
- Formularios y acciones principales se completan solo con teclado; el pipeline tiene alternativa de lista.
- El QA final de la lección 9.3 incluye revisión en móvil real o emulado y corrige los defectos encontrados.
RF-13 Datos demo ficticios para mostrar la aplicación sin información real
Un seed reproducible llena un workspace de demostración con datos inventados para enseñar, probar y grabar la demo sin exponer a ninguna persona real.
Criterios de aceptación (5)
- Existe una función de seed (seed_demo_data) que carga en un workspace 6 empresas, 12 contactos, 8 oportunidades repartidas por las seis etapas, 10 tareas (vencidas, de hoy, próximas, completadas y una cancelada) y 15 actividades de tipos distintos. Las cuentas de las dos personas ficticias se crean desde /register, porque el seed no puede escribir en auth.users.
- Nombres, correos y teléfonos son inventados, con dominios reservados para ejemplos (ejemplo.test, ejemplo.es o example.com), y no coinciden con personas ni empresas reales.
- El seed es idempotente: si el workspace ya tiene empresas no vuelve a sembrar, así que se puede ejecutar dos veces sin duplicar registros.
- El seed es security invoker: solo siembra en un workspace del que ya eres miembro, así que no permite escribir en datos ajenos.
- Los KPIs del dashboard calculados sobre el seed coinciden con los valores esperados en los tests.
Modelo de datos
9 tablas con seguridad por filas
Todas las tablas de negocio cuelgan de un workspace y están protegidas con políticas Row Level Security: cada equipo solo ve lo suyo.
Relaciones tabla a tabla
profiles
- profiles.id → auth.users.id (1:1, obligatorio)
workspaces
- workspaces.owner_id → profiles.id (N:1, obligatorio)
workspace_members
- workspace_members.workspace_id → workspaces.id (N:1, obligatorio)
- workspace_members.user_id → profiles.id (N:1, obligatorio)
companies
- companies.workspace_id → workspaces.id (N:1, obligatorio)
contacts
- contacts.workspace_id → workspaces.id (N:1, obligatorio)
- contacts.company_id → companies.id (N:1, opcional)
deal_stages
- deal_stages.workspace_id → workspaces.id (N:1, obligatorio)
deals
- deals.workspace_id → workspaces.id (N:1, obligatorio)
- deals.company_id → companies.id (N:1, opcional)
- deals.contact_id → contacts.id (N:1, opcional)
- deals.stage_id → deal_stages.id (N:1, obligatorio)
tasks
- tasks.workspace_id → workspaces.id (N:1, obligatorio)
- tasks.assignee_id → profiles.id (N:1, opcional)
- tasks.contact_id → contacts.id (N:1, opcional)
- tasks.deal_id → deals.id (N:1, opcional)
activities
- activities.workspace_id → workspaces.id (N:1, obligatorio)
- activities.contact_id → contacts.id (N:1, opcional)
- activities.deal_id → deals.id (N:1, opcional)
- activities.actor_id → profiles.id (N:1, opcional)
Qué guarda cada tabla
| Entidad | Tabla | Qué guarda | Campos |
|---|---|---|---|
| Perfil | profiles | Datos públicos de cada usuario registrado. Se crea automáticamente con un trigger sobre auth.users y comparte el mismo id. Cada persona lee su perfil y el de quienes comparten workspace con ella, para poder mostrar autoría y responsables. | 3 |
| Workspace | workspaces | Espacio de trabajo de un negocio. Todos los datos comerciales pertenecen a un workspace y el aislamiento entre workspaces lo garantiza RLS. Se crea con la función create_workspace_with_owner, que en la misma transacción inserta también la membresía owner y las seis etapas del pipeline. | 4 |
| Miembro de workspace | workspace_members | Relación entre personas y workspaces con su rol. Clave primaria compuesta (workspace_id, user_id). Es la tabla que consulta la función de membresía usada por todas las políticas RLS. Un trigger impide eliminar o degradar a la persona propietaria. | 4 |
| Empresa | companies | Organización cliente o potencial cliente. Agrupa contactos y oportunidades. Índices sobre workspace_id y sobre (workspace_id, lower(name)) para la búsqueda por nombre. | 9 |
| Contacto | contacts | Persona con la que el negocio se relaciona. Puede pertenecer a una empresa. Índices sobre workspace_id, company_id, (workspace_id, lower(email)) para la búsqueda por correo y next_follow_up_at para ordenar los seguimientos previstos. | 13 |
| Etapa de pipeline | deal_stages | Etapas configurables por workspace. create_workspace_with_owner crea seis: Nuevo, Cualificado, Propuesta, Negociación, Ganado (is_closed e is_won) y Perdido (is_closed). Restricción única sobre (workspace_id, position) e índice sobre workspace_id. | 7 |
| Oportunidad | deals | Venta potencial con valor esperado y etapa. Índices sobre workspace_id, stage_id, company_id, contact_id y expected_close_date. Constraints: amount >= 0 y probability entre 0 y 100. No existe columna de fecha de cierre: una venta cuenta como ganada del mes cuando su etapa tiene is_won y su updated_at cae en el mes en curso. | 12 |
| Tarea | tasks | Acción de seguimiento con fecha límite, prioridad y responsable. Índices sobre workspace_id, due_date, status, assignee_id, contact_id y deal_id: las columnas por las que filtran las vistas y las relaciones. | 13 |
| Actividad | activities | Historial de eventos de contactos y oportunidades: notas manuales y eventos automáticos. Solo se inserta; nunca se edita. Índices sobre (workspace_id, created_at desc), (contact_id, created_at desc), (deal_id, created_at desc) y actor_id. | 9 |
Hitos
El proyecto avanza en cinco entregas
En cada hito registras evidencias concretas (archivos, capturas, enlaces o commits) que quedan guardadas en tu perfil.
- Hito 16 entregables
Cuentas y entorno
Tienes claro qué vas a construir y para quién, has redactado tu primer prompt profesional y tu ordenador, GitHub, Vercel y Supabase están conectados sin haber expuesto ninguna contraseña ni API key. El repositorio ya contiene la memoria persistente del asistente.
- Ficha del negocio en docs/product/brief.mdArchivo
- Prompt de bootstrap en docs/prompts/01-bootstrap.mdArchivo
- Captura de terminal con versionesCaptura
- Archivos persistentes del asistenteArchivo
- Repositorio privado en GitHubEnlace
- Primer deployment de prueba en VercelEnlace
- Hito 26 entregables
Repositorio y UI
Has convertido la idea en usuarios, flujos, historias con criterios de aceptación y un mapa de pantallas. El proyecto Next.js arranca en local, tiene sistema visual, shell de navegación y cinco pantallas estáticas con sus estados, y el historial de GitHub cuenta lo que ha pasado con commits semánticos.
- Usuarios y flujos en docs/product/users-and-flows.mdArchivo
- Historias de usuario en docs/product/user-stories.mdArchivo
- Navegación y campos en docs/product/navigation-and-fields.mdArchivo
- Proyecto Next.js corriendo en localCaptura
- Cinco pantallas estáticas navegablesCaptura
- Historial con commits semánticosCommit
- Hito 35 entregables
Datos seguros
La base de datos existe con sus nueve tablas, claves, índices y constraints; hay datos ficticios; una persona puede registrarse, entrar y salir; y RLS impide que nadie lea o escriba datos de otro workspace. No se avanza al siguiente hito si alguna tabla de negocio está sin RLS.
- Migraciones en supabase/migrations/0001_init.sql y 0002_rls.sqlArchivo
- Diagrama y tablas en docs/data-model.mdArchivo
- Datos ficticios en SupabaseCaptura
- Flujo de autenticaciónVídeo
- Prueba de aislamiento RLSTexto
- Hito 46 entregables
CRM funcional
NexoCRM funciona de punta a punta con Supabase: contactos y empresas con búsqueda, filtros y formularios validados; oportunidades con pipeline y actividad automática; tareas con filtros útiles; timeline con notas; búsqueda global y dashboard con KPIs correctos. Todo con estados de carga, vacío y error cuidados.
- .env.example completoArchivo
- CRUD de contactos y empresasCaptura
- Transición de etapa en el pipelineCaptura
- Timeline de actividadCaptura
- Demo de búsqueda globalVídeo
- Dashboard con datos y sin datosCaptura
- Hito 56 entregables
Publicación
La aplicación está publicada en Vercel con las variables correctas, los tests pasan, el QA final está documentado con sus correcciones, el README permite que otra persona continúe y existe una hoja de ruta razonada. Es el punto de partida para seguir mejorando el CRM con Claude Code o Codex.
- Tests en verdeTexto
- URL pública en VercelEnlace
- QA final en docs/qa/final-checklist.mdArchivo
- README revisable por otra personaArchivo
- Demo de productoVídeo
- Hoja de ruta en docs/product/roadmap.mdArchivo
Pantallas
Las rutas que construyes
Este es el mapa completo de la aplicación: tres pantallas públicas de acceso y el resto protegidas por sesión y membresía.
| Ruta | Para qué sirve |
|---|---|
| / | Redirige a /dashboard si hay sesión y a /login si no la hay. |
| /login | Inicio de sesión con correo y contraseña; enlaza a registro y recuperación. |
| /register | Alta de una cuenta nueva con nombre completo, correo y contraseña. |
| /forgot-password | Solicitud del correo de recuperación de contraseña sin revelar si el correo existe. |
| /dashboard | Inicio privado: cinco KPIs, pipeline resumido, tareas urgentes y próximos seguimientos con enlace a la acción siguiente. |
| /contacts | Listado de contactos con búsqueda por nombre, correo y teléfono y filtros por estado y empresa (?q=, ?status=, ?companyId=). |
| /contacts/new | Formulario de alta de contacto con validación Zod y empresa opcional. |
| /contacts/[id] | Ficha del contacto: datos, empresa, oportunidades, tareas, timeline con notas y edición. |
| /companies | Listado de empresas con búsqueda por nombre y sector (?q=). |
| /companies/new | Formulario de alta de empresa con validación de nombre y web. |
| /companies/[id] | Ficha de la empresa: datos, contactos relacionados, oportunidades abiertas, actividad reciente y edición. |
| /deals | Listado de oportunidades con importe, probabilidad, etapa y valor ponderado, filtrable por estado, etapa y texto (?status=open|won|lost|all, ?stageId=, ?q=). |
| /deals/new | Formulario de alta de oportunidad con empresa, contacto, importe, probabilidad, fecha esperada y etapa. |
| /deals/[id] | Ficha de la oportunidad: datos, cierre como ganada o perdida, cambio de etapa, tareas y timeline. |
| /pipeline | Tablero por etapas con recuento e importe por columna, vista de lista accesible y cambio de etapa persistido. |
| /tasks | Gestión de tareas con prioridad, responsable y relación con contacto u oportunidad; vistas ?view=pending (por defecto), today, overdue, upcoming, done y all. |
| /settings/workspace | Nombre del workspace; editable solo por owner. |
| /settings/members | Listado de miembros con su rol; alta y baja de miembros solo para owner. |
Cómo sabrás que funciona
- El 100 % de las oportunidades abiertas del negocio están registradas en NexoCRM con importe, etapa y fecha esperada.
- Crear un contacto completo con empresa asociada cuesta menos de 60 segundos desde el listado.
- Al cerrar cada semana no queda ninguna tarea atrasada sin responsable; el filtro de atrasadas se revisa a diario.
- El dashboard responde a las cinco preguntas clave (oportunidades activas, valor ponderado, ganadas del mes, tareas vencidas y próximos seguimientos) sin abrir otra pantalla.
- Un usuario de otro workspace no puede leer ni escribir datos ajenos: la prueba de aislamiento RLS pasa en cada cambio de esquema.
- La aplicación publicada en Vercel muestra el dashboard en menos de 3 segundos en una conexión móvil y se maneja completa con teclado.