Portal de clientes Growork
Diseñé y construí el área privada donde cada cliente puede seguir su búsqueda de empleo en Suiza con datos reales: candidaturas enviadas, respuestas recibidas, documentos, plan contratado, rendimiento y ayuda contextual con IA.
7
módulos privados conectados
5
sistemas sincronizados
0
mocks en la experiencia del cliente
El reto
Growork no vendía solo una página atractiva. Detrás había una operación real: buscar hoteles, enviar candidaturas, gestionar respuestas, actualizar documentos, activar planes, registrar pagos y mantener sincronizados CRM, base de datos, web interna y automatizaciones.
El problema era que gran parte de ese trabajo quedaba invisible. Para el cliente, si no había un mensaje, parecía que no pasaba nada. Y, para el equipo, responder una y otra vez a preguntas de seguimiento no escalaba.
El objetivo del portal fue convertir una operativa compleja en una sensación clara de avance: esto es lo que hemos enviado, esto ha respondido, esto te queda de plan y esto puedes hacer ahora.
Qué construí
Construí una capa privada bajo /portal/* que funciona como un producto SaaS para candidatos. No es una página de estado: es una interfaz conectada a la operativa diaria de Growork, con rutas protegidas, paywall interno, datos por cliente y flujos preparados para usuarios individuales o de pareja.
Dashboard
Vista ejecutiva del caso: candidaturas enviadas, respuestas, actividad reciente, ciudades objetivo, ciudades ya contactadas y días restantes del plan.
Candidaturas
Tabla filtrable de hoteles y empresas contactadas, con estados entendibles para el cliente: enviada, abierta, respondida, entrevista o descartada.
Respuestas
Bandeja privada con respuestas clasificadas, contador de no leídas, hilo de conversación, sugerencia de respuesta y envío directo en hilo.
Estadísticas
Métricas de campaña por periodo con Chart.js: tasa de respuesta, enviados, entrevistas, regiones con más tracción y tipos de respuesta.
Mi plan
Estado del servicio contratado, historial, renovación, upgrades y activación diferida cuando aparece la primera candidatura real.
Perfil
Datos personales, información profesional y subida segura de CV y carta en PDF, también preparada para cuentas de pareja.
Chat IA
Asistente contextual con datos reales del cliente, límites de uso, sanitización de prompts y alcance restringido a Growork.
Antes y después
El portal cambió la percepción del servicio: de una operación que podía sentirse invisible a una experiencia donde el cliente ve progreso, contexto y valor después de comprar.
Antes
Antes: el cliente dependía de mensajes manuales para saber si su búsqueda avanzaba.
Después
Después: entra al portal y ve candidaturas, respuestas, documentos, rendimiento, plan y siguientes pasos con datos reales.
Antes
Antes: la operación estaba repartida entre CRM, web interna, pagos, documentos y automatizaciones.
Después
Después: el portal actúa como una capa clara encima de esas fuentes sin exponer la complejidad técnica.
Antes
Antes: muchas preguntas se repetían porque el progreso no era visible.
Después
Después: el panel reduce la incertidumbre, baja el soporte repetitivo y aumenta la confianza en el servicio.
Arquitectura del portal
El portal actúa como una capa de producto sobre varios sistemas. Cada fuente tiene una responsabilidad distinta y el frontend no habla directamente con los servicios sensibles: el servidor valida la sesión, resuelve el cliente vinculado y consulta lo necesario a través de APIs protegidas.
Lo difícil no era pintar tablas
La complejidad real estaba en que el portal tenía que ser fiel a lo que pasaba fuera de él. No podía inventarse progreso, no podía perder documentos, no podía mezclar clientes y no podía romperse cuando un webhook o una automatización llegaba tarde.
Una operación invisible para el cliente
Growork mueve emails, hoteles, respuestas, documentos, pagos, planes, CRM y automatizaciones. El portal convierte todo eso en una experiencia simple: el cliente entra y entiende qué está pasando.
Fuentes de verdad repartidas
PostgreSQL guarda usuarios, sesiones, servicios, pagos, rate limits y chat. Twenty CRM mantiene el perfil comercial. La web interna aporta candidaturas, respuestas, documentos y métricas. Stripe confirma las compras. El portal orquesta todo sin exponer esa complejidad.
Planes que empiezan cuando tiene sentido
Si alguien paga hoy pero la primera candidatura sale días después, el reloj del plan no debería correr desde el pago. Implementé activación diferida: el servicio se guarda al comprar, pero empieza con el primer envío real.
Modo pareja de verdad
No era duplicar un formulario. Había que soportar dos emails, dos CV, dos perfiles, vinculación en el CRM, precio de pareja, documentos separados, plan compartido y visibilidad correcta dentro del portal.
Sesión preparada para datos asíncronos
El sistema contempla escenarios imperfectos: usuarios creados por Stripe, entidades que Twenty transforma después, identificadores que cambian y cookies que deben refrescarse sin romper la sesión.
Seguridad en todas las entradas
JWT en cookies HTTP-only firmado con jose, bcrypt, bloqueo tras intentos fallidos, rate limits persistidos, tokens de un solo uso, validación real de PDF, proxy server-side con API key y comprobación de pertenencia antes de servir adjuntos.
Seguridad e IA contextual
La parte sensible del portal no era solo autenticar usuarios. Había que proteger documentos personales, adjuntos, pagos, sesiones y un asistente IA que conoce el contexto del cliente sin convertirse en una puerta abierta a los datos internos.
Contexto acotado
El chat recibe solo los datos necesarios del caso y queda restringido a Growork, búsqueda de empleo en Suiza, plan, candidaturas, respuestas y perfil.
Controles de abuso
Rate limits por hora, día y mes, sanitización de prompts, validación de pertenencia antes de servir adjuntos y APIs protegidas server-side.
Contrato de API
Endpoints protegidos del portal
De los 33 endpoints del área del portal, estos resumen cómo se resuelve la sesión, se protegen los documentos y se mantienen los hilos de conversación.
/api/portal/meResuelve la sesión a partir de la cookie firmada y devuelve el contexto del usuario y su pareja.
auth: JWT en cookie HTTP-only
/api/portal/candidaturas/[id]/attachments/[filename]Sirve un adjunto solo tras comprobar que pertenece al cliente autenticado; proxy server-side hacia la web interna.
auth: JWT + comprobación de propiedad
/api/portal/respuestas/send-replyResponde a un hotel manteniendo el hilo (In-Reply-To, References, threadId de Gmail).
auth: JWT
/api/portal/chatChat IA con contexto acotado, sanitización de prompts y límites por hora, día y mes.
auth: JWT + rate limit
Decisiones de producto e ingeniería
No hacer un dashboard decorativo
El portal no usa datos falsos para parecer activo. Cada vista se alimenta de datos operativos reales: emails enviados, respuestas, documentos, estado del plan y actividad del caso.
Traducir estados técnicos a lenguaje de cliente
La operativa interna puede tener estados complejos. En el portal se reducen a conceptos claros: enviada, abierta, respondida, entrevista o descartada.
Poner límites al chat IA
El asistente solo recibe el contexto permitido del cliente y solo puede hablar de Growork, búsqueda de empleo en Suiza, plan, candidaturas, respuestas y perfil. Tiene rate limits por hora, día y mes.
Proteger los documentos como datos sensibles
Los CV, cartas y adjuntos pasan por validación de tipo, tamaño y magic bytes. Los nombres se sanitizan y las descargas se validan server-side antes de devolver archivos.
Stack con intención
Cada tecnología aparece porque resolvía una parte concreta del sistema, no para engrosar una lista.
Next.js + React
Portal privado con App Router, Server Components para la carga de datos y Client Components donde había interacción real.
TypeScript
Contratos claros entre APIs, modelos de UI, respuestas del backend interno y datos del CRM.
PostgreSQL
Estado propio del portal: usuarios, servicios, pagos, sesiones auxiliares, tokens, rate limits y mensajes del chat.
jose + bcryptjs
Sesión JWT firmada (HS256) en cookie HTTP-only y contraseñas hasheadas con bcrypt.
Twenty CRM
Perfil comercial, clientes, parejas, estado del plan y sincronización con la operativa de Growork.
Stripe
Pagos, renovaciones, upgrades, checkout invitado y aprovisionamiento posterior mediante webhooks.
Web interna
Fuente operativa de candidaturas enviadas, respuestas recibidas, adjuntos, documentos y métricas de rendimiento.
OpenAI
Chat privado con contexto acotado, sanitización de prompts y controles de abuso.
Impacto
El portal no fue una mejora cosmética. Fue una forma de aumentar la confianza del cliente, reducir el trabajo manual y dar a Growork una experiencia privada a la altura de lo que ya ocurría en operaciones.
Cliente
Gana visibilidad y control: entiende qué se ha hecho, qué respuesta ha llegado, cuánto plan le queda y qué documentos siguen activos.
Empresa
Gana escala operativa: menos seguimiento manual, mejor trazabilidad, menos dudas repetidas y una experiencia premium después del pago.
Producto
Gana coherencia: pagos, CRM, candidaturas, documentos e IA dejan de ser piezas aisladas y se convierten en una experiencia privada.
Lo que demuestra
- →Aprendizaje autodidacta aplicado a un problema real: leer documentación, probar APIs, validar hipótesis y convertir errores de integración en diseño defensivo.
- →Capacidad para pensar en producto después del checkout: no solo vender, sino sostener la confianza durante la prestación del servicio.
- →Criterio para equilibrar experiencia y seguridad cuando hay documentos personales, pagos, sesiones privadas e IA con contexto de usuario.
- →Capacidad para convertir un proceso operativo real en una experiencia de producto clara.
- →Criterio para decidir qué sistema es la fuente de verdad para cada dato.
- →Experiencia conectando pagos, CRM, base de datos propia, backend interno, automatizaciones e IA.
- →Seguridad aplicada desde el diseño, no como una capa al final.
- →Pensamiento de producto: activación diferida, lenguaje entendible, modo pareja y reducción de fricción.
- →Frontend orientado a que el cliente entienda el progreso, no a mostrar la complejidad técnica.