Proyecto para el proceso de entrevista de SALMA
TXT.Lib es una plataforma completa para gestionar textos y generar audios a partir de ellos utilizando ElevenLabs. El proyecto incluye:
- ✅ Generación de audio con ElevenLabs (voces masculinas y femeninas)
- ✅ Almacenamiento en la nube con Supabase Storage (persistente)
- ✅ Compartir textos entre usuarios dentro de la plataforma
- ✅ Analytics completos con estadísticas de uso y reproducciones
- ✅ Integración con WhatsApp vía Kapso para enviar audios y textos
- ✅ Sistema de favoritos y gestión de biblioteca personal
- ✅ Verificación de teléfono y configuración de notificaciones
- Framework: Node.js + Express
- Arquitectura: MVC (Modelo-Vista-Controlador)
- Puerto: 3000
- Base de datos: Supabase (PostgreSQL)
- Autenticación: JWT personalizado (sin usar Supabase Auth)
- Almacenamiento de audio: Supabase Storage (bucket
audiofiles) - Text-to-Speech: ElevenLabs SDK oficial
- Framework: Next.js
- Build: Estático (Static Site Generation)
- Puerto dev: 5173 (como React puro)
- UI: Tailwind CSS con diseño minimalista oscuro
- Plataforma: Render
- Configuración: Mono-repo (frontend + backend en el mismo servidor)
- Nota importante: Render en tier gratuito puede tardar ~1 minuto en arrancar cuando está inactivo
- Crea una cuenta en Supabase
- Crea un nuevo proyecto
- Ve al SQL Editor
- Copia y pega el contenido de
db.sql(ubicado en la raíz del proyecto) - Ejecuta el script para crear todas las tablas, funciones y triggers
- Ve a Storage en tu proyecto de Supabase
- Crea un nuevo bucket llamado
audiofiles - Marca la opción Public bucket (para que los audios sean accesibles)
- Guarda el bucket
users- Usuarios con autenticación personalizadatexts- Textos creados por usuariosshared_texts- Sistema de compartir entre usuariosfavorites- Favoritos por usuarioaudio_analytics- Tracking de reproduccioneswhatsapp_config- Configuración de WhatsApp por usuariowhatsapp_notifications- Historial de mensajes enviados
Crea un archivo .env en la carpeta raíz:
# ==========================================
# SUPABASE
# ==========================================
SUPABASE_URL=https://tu-proyecto.supabase.co
SUPABASE_SECRET_KEY=tu-supabase-secret-key
# ==========================================
# JWT
# ==========================================
JWT_SECRET=tu-jwt-secret-super-seguro
# ==========================================
# SERVER
# ==========================================
NODE_ENV=development
PORT=3000
BASE_URL=http://localhost:3000
# ==========================================
# ELEVENLABS (Text-to-Speech)
# ==========================================
ELEVENLABS_API_KEY=tu-elevenlabs-api-key
# ==========================================
# KAPSO (WhatsApp)
# ==========================================
KAPSO_API_KEY=tu-kapso-api-key
KAPSO_PHONE_SANDBOX=tu-numero-sandbox-kapsoCrea un archivo .env.local en la carpeta frontend:
NEXT_PUBLIC_API_URL=http://localhost:3000/api- Ve a tu proyecto en Supabase
- Settings → API
- Copia
URLyservice_role key
- Crea cuenta en ElevenLabs
- Ve a Profile → API Keys
- Copia tu API key
- Nota: El tier gratuito no funciona desde servidores/VPNs, requiere plan de pago ($5/mes mínimo)
- Crea cuenta en Kapso
- Obtén tu API key y número de sandbox
Desde la raíz del proyecto, ejecuta:
npm run buildEste comando hace:
- ✅ Instala dependencias del backend
- ✅ Instala dependencias del frontend
- ✅ Hace build estático de Next.js
- ✅ Configura todo para correr en puerto 3000
Luego inicia el servidor:
npm startLa aplicación estará disponible en: http://localhost:3000
# Instalar dependencias de ambos proyectos
npm install
# Build completo (backend + frontend)
npm run build
# Iniciar servidor en producción
npm start
# Desarrollo del backend (solo backend)
npm run dev
# Desarrollo del frontend (con hot reload)
cd frontend && npm run devTXT.Lib/
├── src/ # Backend
│ ├── config/
│ │ ├── supabase.js # Configuración Supabase
│ │ ├── kapso.js # Configuración Kapso
│ │ └── elevenlabs.js # Generación de audio + Storage
│ ├── controllers/ # Controladores MVC
│ │ ├── auth.controller.js
│ │ ├── texts.controller.js
│ │ ├── analytics.controller.js
│ │ ├── whatsapp.controller.js
│ │ ├── shared.controller.js
│ │ ├── favorites.controller.js
│ │ └── users.controller.js
│ ├── routes/ # Rutas API
│ ├── middleware/ # Middlewares (auth, etc)
│ └── utils/ # Utilidades
│ ├── app.js # Servidor Express principal
├── client/ # Frontend Next.js
│ ├── app/ # App router de Next.js
│ ├── components/ # Componentes React
│ ├── utils/ # API calls y utilidades
│ └── types/ # TypeScript types
├── db.txt # Script SQL de base de datos
├── package.json # Dependencias backend
└── README.md # Este archivo
- Crear, editar y eliminar textos
- Organizar por categorías
- Sistema de búsqueda y filtros
- Contador de palabras automático
- Modal de confirmación para eliminación
- Integración con ElevenLabs SDK oficial
- Voces masculinas y femeninas
- Reproducción en línea con controles interactivos
- Timeline clickeable para navegar el audio
- Descarga de archivos MP3
- Almacenamiento persistente en Supabase Storage
- Compartir textos con otros usuarios
- Búsqueda de usuarios estilo GitHub
- Permisos configurables (solo lectura o edición)
- Vista separada de "Mis Textos" y "Compartidos Conmigo"
- Dashboard con métricas principales
- Top 5 textos más reproducidos
- Actividad reciente
- Tiempo total de audio generado
- Gráficas de textos por mes
- Tracking automático de reproducciones
- Marcar textos favoritos
- Acceso rápido desde el dashboard
- Estadísticas de favoritos
- Enviar solo audio
- Enviar solo texto
- Enviar texto + audio
- Verificación de número con código
- Envío a uno mismo (envío a otros próximamente)
- Mensajes de error descriptivos para problemas comunes
- Información básica de cuenta
- Estadísticas personales
- Configuración de WhatsApp
- Verificación de número telefónico
Sistema personalizado con JWT:
- Registro de usuarios
- Login con email/password
- Tokens almacenados en cookies HTTP-only
- Middleware de autenticación en todas las rutas protegidas
El sistema trackea automáticamente:
- Cada reproducción de audio
- Duración de escucha
- Audios completados
- Descargas de audio
- Textos compartidos
- Favoritos agregados
- Conecta tu repositorio a Render
- Configura como Web Service
- Build Command:
npm run build - Start Command:
npm start - Agrega todas las variables de entorno
- Importante: Actualiza
BASE_URLcon tu dominio de producción
⚠️ En tier gratuito, el servidor se duerme después de inactividad⚠️ Primera carga puede tardar ~1 minuto- ✅ Audios almacenados en Supabase Storage (persistentes entre deploys)
- ✅ WhatsApp requiere URLs HTTPS (Render incluye SSL gratis)
- ✅ ElevenLabs requiere plan de pago para funcionar desde servidores
Inicialmente se usaba almacenamiento local, pero los archivos se perdían con cada redeploy en Render. Supabase Storage ofrece persistencia gratuita y URLs públicas para los audios.
Aunque Supabase tiene su propio sistema de auth, decidí implementar JWT personalizado para tener mayor control y demostrar conocimiento en autenticación custom.
Para simplificar el despliegue en Render y poder servir todo desde un solo servidor en el puerto 3000, evitando complejidad de infraestructura.
Migramos de axios directo al SDK oficial de ElevenLabs para mejor manejo de streams, autenticación y errores.
- Sistema de notificaciones: Notificaciones en tiempo real cuando alguien comparte un texto contigo o reproduce tu audio
- Compartir por WhatsApp a otros usuarios: Actualmente solo se puede enviar a uno mismo, habilitar envío a cualquier número
- Auth persistence en frontend: Implementar persistencia de sesión en el cliente para mejor UX (no implementado por tiempo)
- Sistema de recomendaciones inteligente: Usar el historial de reproducciones y favoritos para sugerir textos similares
- Chat conversacional con MCP: Integrar Model Context Protocol de Kapso para conversaciones interactivas por WhatsApp
- Rate limiting: Protección contra abuso y bots maliciosos en los endpoints de la API
- Múltiples voces: Expandir opciones de voces más allá de masculina/femenina
- Exportación de analytics: Descargar reportes en CSV/PDF
- Modo offline: Cachear audios para reproducción sin conexión
- API pública: Documentar y exponer API para integraciones de terceros
- Node.js 18+
- Express.js
- Supabase (PostgreSQL + Storage)
- JWT (jsonwebtoken)
- bcryptjs
- ElevenLabs SDK (@elevenlabs/elevenlabs-js)
- Kapso SDK (@kapso/whatsapp-cloud-api)
- ES Modules
- Next.js 14
- React 18
- TypeScript
- Tailwind CSS
- Lucide React (iconos)
- Render (hosting)
- Supabase (base de datos + storage)
- Git (control de versiones)
- Primer arranque: En Render gratuito, la primera carga tarda ~1 minuto
- Audios: Se guardan en Supabase Storage (bucket
audiofiles) - Base de datos: Ejecutar
db.sqlen Supabase antes de usar - WhatsApp: Requiere verificación de número y ventana de 24 horas activa
- ElevenLabs: Requiere plan de pago para funcionar desde servidores
- Verifica que todas las variables de entorno estén configuradas
- Revisa que el puerto 3000 esté disponible
- Comprueba las credenciales de Supabase
- Verifica tu API key de ElevenLabs
- Importante: El tier gratuito de ElevenLabs no funciona desde servidores, necesitas plan de pago
- Comprueba que el bucket
audiofilesexista en Supabase Storage - Revisa los logs de error del servidor
- "Sesión expirada": Envía "hola" al número de TXT.Lib en WhatsApp para reactivar la ventana de 24 horas
- Verifica que tu número esté verificado en la app
- Comprueba las credenciales de Kapso
- Verifica que el bucket
audiofilessea público en Supabase - Comprueba la URL del audio en la consola del navegador
- Para audios legacy (almacenados localmente), pueden haberse perdido con un redeploy
Este proyecto fue desarrollado por Julián Catalán como parte del proceso de entrevista para SALMA.
Este proyecto es de código privado para evaluación técnica.
¡Gracias por revisar TXT.Lib! 🎉