WspWrapped: métricas de chat sin guardar un solo mensaje
Subes un chat exportado de WhatsApp y obtienes 30+ métricas de la conversación — sin guardar un solo mensaje.
- Tipo
- App de Consumo
- Año
- 2026
- Rol
- Founder / Product Engineer
- Stack
- Next.js · TypeScript · Supabase · Vercel
- Estado
- En producción

Por Jorge CortésPublicado el
Resumen
Construí WspWrapped para que cualquiera suba un export de WhatsApp y reciba más de 30 métricas de la conversación sin guardar el texto. El parser corre en memoria. Solo persisten agregados. La privacidad es la arquitectura. Lo que la landing llama «IA» tiene que correr sobre esos números, no sobre el chat — o es copy sobre features.
Problema
WhatsApp es cómo habla la gente. También es un log que nadie lee como dato. Cada chat 1:1 y cada grupo esconde las mismas preguntas: quién escribe más, quién empieza, quién contesta a las 3am, quién se calla, quién borra. La gente discute de memoria. Captura una racha. No ve un año.
WhatsApp ya tiene Exportar chat: Opciones, Más, Exportar chat. Sin archivos multimedia el archivo pesa menos. Sale un .txt, o un .zip que igual envuelve un .txt. El archivo es marcas de tiempo, nombres y líneas. No se puede leer como métrica. Ese es el hueco.
No partí de «ponerle IA a los chats». Partí de un archivo que el usuario ya tiene. La landing lista las preguntas porque son el trabajo: quién tarda más, quién hace ghosting, quién inicia, quién borra, quién se desvela. Los datos están en el export. El trabajo es convertirlos en números sin convertirlos en una base de mensajes ajenos.
Un producto de consumo tiene un segundo trabajo que el log no tiene: una tarjeta para publicar. Nadie abre un CSV un viernes. Abren Stories. Si el reporte no sale del dashboard en 9:16, el producto muere en una carpeta de capturas.
Restricciones
Un chat personal no es telemetría. Si persisto el texto, me convierto en un almacén de datos íntimos. Ese producto no lo quiero operar. La landing dice 100% privado. El FAQ dice que no guardamos el contenido de mensajes ni archivos. La arquitectura tiene que hacerlo cierto.
El formato del export no es una spec mía. Android e iPhone escriben líneas distintas. Los locales escriben fechas dd/mm/yyyy o m/d/yy. Algunas líneas meten la hora entre corchetes con segundos. Algunas inyectan marcas Unicode de izquierda a derecha. «Sin archivos multimedia» igual comprime un texto. Los mensajes de sistema están localizados: "This message was deleted", "Este mensaje fue eliminado", "Mensagem apagada". Si el parser asume un solo locale, miente.
Publico en Vercel. Descomprimir y cargar decenas de megabytes de texto en una función serverless choca con tiempo y memoria. Un chat de 50MB es un export real, no un caso raro.
El uso es episódico. Un chat, una vez, para una story. Una suscripción mensual pelea con esa forma. Los créditos tienen que existir sin convertir la cuenta en el chat.
La UI del producto sale en español, inglés y portugués. La raíz con ES seleccionado es español. EN vive en /en. PT vive en /pt. El parser tiene que sobrevivir los tres locales dentro del archivo, no solo en el header.
Grupo y 1:1 comparten un pipeline. El análisis se adapta. No puedo asumir dos participantes. No puedo asumir una pareja.
Las tarjetas son HD, 9:16, hechas para Stories, Reels y TikTok. El copy Pro en la página portuguesa dice exportar en HD sin marca de agua. Un link único para compartir es un segundo camino. No tengo conteos de impresiones. «Viral» en la landing es marketing, no una métrica que pueda defender.
Trabajo como ingeniero de producto desde Santiago. La página canónica es Jorge Cortés.
Arquitectura que diseñé
El usuario exporta un chat, suelta un .txt o un .zip y recibe un reporte. El último nodo es una tarjeta social, no un CRM. La landing dice métricas en segundos: afirmación del producto, no un benchmark que yo haya publicado.
El archivo nunca se escribe en una tabla de mensajes. El parse ocurre en memoria del request, o en un worker de vida corta, o en el dispositivo. Persisto agregados en Supabase para que existan el link para compartir y el débito de un crédito: conteos, histogramas, scores, etiquetas de participantes que el usuario ya ve. El texto crudo se descarta. La sesión no es el chat.
El FAQ se contradice. Una respuesta dice que se procesa en local sin guardar mensajes. Otra dice que se procesa en memoria y solo se guardan agregados estadísticos: números, no texto. En local puede ser el navegador. En memoria, una función que muere al terminar el request. No he publicado el runtime aquí.
Los créditos viven en la cuenta en Supabase: créditos restantes, no mensajes. Hay auth. El header tiene Iniciar sesión. El alta es gratis. La sesión es la billetera detrás de una URL para compartir, no una réplica del export.
Los packs son públicos. Un crédito equivale a un reporte completo. Tres créditos cuestan $2.99. Diez créditos cuestan $4.99. Los créditos no vencen. No hay cuotas recurrentes. Pro es el desbloqueo de 30+. La capa gratis son métricas básicas. El checkout no aparece en la landing con un proveedor nombrado.
No observé un procesador de pago en las páginas públicas. No voy a inventar uno.
Stack y por qué
Next.js es el producto: tres locales, la landing, la subida, el reporte, la página para compartir. Los locales del header son rutas, no un plugin.
TypeScript no es moda en un parser. El export es texto sucio. Los tipos mantienen honestas las clases de línea: mensaje de usuario, lápida de sistema, media omitida, encabezado de fecha. Sin eso, el parser se vuelve folclore de regex.
Supabase es auth, créditos y filas de agregados. No es un lago de mensajes. Si una tabla parece un chat, diseñé el almacén mal. El control de acceso va sobre la cuenta, no sobre las frases de otros.
Vercel es donde corre el sitio. Tiempo y memoria serverless son parte del producto. Un worker, un handler en Edge o el cliente responden al mismo límite. Stack: Next.js, TypeScript, Supabase, Vercel. Año 2026. Rol: Founder / Product Engineer.
La diferencia con otros productos que saqué con los mismos cuatro nombres es el contrato de datos. WspWrapped puede recordar números. No puede recordar oraciones.
Decisiones técnicas
Tirar el texto. Quedarse con el histograma. La mayoría de las 30+ superficies son estadística descriptiva. Conteos. Mapas de calor. Distribuciones de tiempo de respuesta. Frecuencia de emojis. Horas de búho. Double-texting. Mensajes eliminados, si el export trae lápida. Iniciativa: quién empieza. Ghosting, tal como lo vende la landing, es un umbral sobre huecos de silencio, no un clasificador que yo haya evidenciado. Si es un modelo, aquí no está documentado.
Nombrar el marketing y después la cuenta. La landing vende Couple Dynamics, Interest Level, Compatibility en cinco dimensiones, AI Predictions, The Roast, Ghosting Zone, Deleted Messages, Hall of Fame, Heatmap, Top Emojis, Romance Score, Night Owls, Double Texting, Psychological Insights. Interest Level se describe como tiempos de respuesta, iniciativa y engagement: features de timestamps y remitentes. Compatibility es un score. Puede ser una suma ponderada. También un modelo. No voy a ascender una etiqueta a red neuronal.
IA como capacidad, no como demo. El producto afirma una capa de IA. «AI Predictions» es el futuro del chat según patrones detectados por inteligencia artificial. Una demo haría POST del transcript entero a un LLM hospedado y pegaría el texto en The Roast. Eso transmite texto. Pelea con el FAQ. Si esas superficies existen en producción, corren sobre agregados y features en el mismo request, o son plantillas.
No nombro un vendor de LLM. No evidencié ninguno. Ese hueco es el ensayo. El trabajo que tomo en sistemas IA es la misma regla: el modelo es una capacidad dentro de un producto con contrato de datos. No es la home.
Créditos, no suscripción. App de consumo, uso de una vez. Pagas cuando quieres las 30+. Las métricas básicas gratis son el embudo. Créditos que no vencen bajan el arrepentimiento. El costo es no tener ingreso mensual previsible. Lo acepté.
Un pipeline, dos formas de chat. Individual y grupo. El motor no se parte en dos apps. La cardinalidad de participantes cambia el reporte. Las etiquetas de pareja son una vista, no un schema de dos filas.
Tarjetas para distribución orgánica. HD, 9:16. Sin marca de agua en Pro, según la página en portugués. Diseñadas para publicarse. El link para compartir no necesita una descarga. No estoy reportando alcance.
El auth es una billetera. Entras para guardar créditos y para ser dueño de una URL. No para que yo relea tu chat la semana que viene.
Problemas que aparecieron
El primer modo de fallo no es un degradado. Es una fecha.
Una línea que parsea en inglés en Android es otra en iPhone, en español, con una marca Unicode antes del corchete. Si parto por comas, me como el campo equivocado. Si asumo m/d/yy, intercambio día y mes para casi toda Latinoamérica. Si ignoro las líneas de sistema, desaparecen los borrados. Si las trato como texto de usuario, invento un participante llamado «Este mensaje fue eliminado».
Los mensajes eliminados son una cota inferior. Solo se cuentan si el export todavía trae la lápida. Si alguien borra para todos y el export lo omite, la métrica calla. Publicar «quién borra más» como número duro sin esa salvedad es mentir. Prefiero una cota inferior a una ficción.
Los chats grandes son el segundo modo de fallo. Descomprimir y parsear en memoria es simple. Lo simple muere en un grupo de un año. Una función serverless que carga 50MB de texto se queda sin tiempo o sin memoria. Streaming es el arreglo obvio y un parser peor. Parsear en el cliente es el otro, con bonus de privacidad: el archivo no sale del dispositivo. Un worker a trozos es el tercero. No voy a afirmar cuál salió a producción.
El tercero es copy versus contrato. La landing habla de algoritmos avanzados y de patrones detectados por inteligencia artificial. El FAQ habla de agregados estadísticos. Los dos pueden convivir en un sitio. Solo uno es un flujo de datos. Si The Roast es una plantilla, llamarlo IA entrena la expectativa equivocada. Si es una llamada a un LLM sobre el texto completo, la arquitectura de privacidad es un afiche. Esa tensión no está resuelta en público.
El cuarto es el paywall después de la curiosidad. Las métricas básicas gratis son el embudo. Si el corte es muy flaco, se van. Si es muy gordo, no compran. No tengo números de conversión.
Cómo los resolví
Traté el export como una familia de formatos, no como una sola regex.
- 01/
Parsear marca de tiempo y remitente aparte del cuerpo. El locale y el OS cambian el lado izquierdo de la línea. El cuerpo no es donde vive la fecha.
- 02/
Catalogar mensajes de sistema en ES, EN y PT. Borrados, media omitida y otras lápidas son conteos, no citas. Si la línea no está, el conteo no sube.
- 03/
Acotar memoria. Fallar si el archivo no cabe en el runtime, o mover el parse al cliente, o trocearlo. El silencio es peor que un error. Qué camino está en producción sigue siendo un TODO.
- 04/
Persistir solo agregados. Las URLs para compartir y los débitos de crédito leen números. Nunca leen un transcript, porque no hay transcript que leer.
- 05/
Vender un pack, no un mes. Un crédito, un reporte completo. Las métricas básicas siguen gratis. Los créditos no vencen: un segundo chat el año que viene sigue pagado.
- 06/
Dejar las etiquetas de IA en el producto si salen, y negarme a mandar el chat a un vendor de modelos que no confirmé. Features adentro, texto afuera.
El arreglo de un mal parse es un mejor parse, no un modelo. El arreglo de la privacidad es no guardar el archivo.
Resultado
- Métricas de conversación
- 30+
- Idiomas (ES, EN, PT)
- 3
- Pack de tres créditos
- $2.99
- Mensajes guardados
- 0
WspWrapped está en producción en 2026, en tres idiomas, con capa gratis y packs de créditos en vez de suscripción. Pro son 30+ métricas por un crédito. Flujo: exportar, soltar .txt o .zip, métricas en segundos, 100% privado — como lo dice el producto.
No publico usuarios, vistas en TikTok ni ingresos. Los números confirmados son superficie: métricas, locales, precio del pack y cero texto guardado.
Evidencia



El producto en vivo es wspwrapped.online. Footer: Privacidad, Términos, Cookies. No invento un DPA.
Qué haría distinto
Separaría en la UI la estadística de la salida de un modelo. Los mapas de calor son conteos. The Roast, si es una plantilla, no debería llevar un sello de IA. Si es un modelo, debería decir que corre sobre features, no sobre el transcript.
Publicaría el runtime del parse. Cliente, route handler, worker. «En memoria» es cierto de muchos diseños malos. «El archivo no sale del dispositivo» es una frase más fuerte, si es verdad.
Si el parse sigue en el servidor, probaría parsear en el cliente como default. El bonus de privacidad es real. El límite serverless desaparece. El costo es un navegador más pesado.
Mantendría la regla de no recalcular. Una métrica nueva pide una subida nueva. No empezaría a guardar texto «solo una semana». Esa semana se vuelve el producto.
No perseguiría conteos virales que no tengo. Tarjetas diseñadas para publicarse son una decisión de diseño que puedo defender. Las vistas no.
Hasta que los TODO reemplacen runtime, columnas, procesador de pago y si The Roast llama a un modelo, defiendo lo que puedo ver: parsear, tirar el texto, guardar números, cobrar un crédito, renderizar una tarjeta.