01En producción60h invertidas

TECI∞ Préstamos

Landing fintech + panel admin completo para una financiera argentina.

Next.jsTypeScriptSupabaseResendVercelTailwind
El problema

Una financiera de Córdoba se lanzaba desde cero y no tenía ningún canal digital: sin landing, sin forma de capturar leads online ni de gestionar solicitudes más allá de WhatsApp informal. Necesitaban un sistema completo antes de operar.

La idea

Landing que simula el préstamo en tiempo real y convierte el interés en un lead estructurado, más un panel admin con pipeline visual, actualización en tiempo real y exports para que el equipo opere desde un solo lugar desde el día uno.

El resultado

Sitio en producción en teciprestamos.com.ar. Panel admin con dashboard de KPIs, tabla de leads con Realtime (sin polling), exports CSV/Excel/PDF, emails transaccionales automáticos al equipo y al solicitante, rate limiting por IP y autenticación segura. La financiera arrancó operando con visibilidad completa del pipeline en vez de depender de WhatsApp informal.

Arquitectura

Next.js 16 App Router con Server Components puros en la landing y Client Components solo donde hay interactividad. Supabase como backend completo.

Landing (RSC)Server Components puros, zero JS en el HTML inicial
ModalLazy-loaded Client Component, solo se descarga cuando el usuario lo abre
API RoutesPOST /api/solicitud con rate limiting por IP via Supabase
Supabase RealtimePanel admin actualiza la tabla en tiempo real con setAuth fix
EmailsResend con templates extraídos en lib/emails/
Decisiones técnicas

¿Cómo trasladar la identidad visual del cliente al código?

elegido

Traducir el PDF de branding (paleta, tipografías, logo) provisto por un diseñador a design tokens reutilizables en Tailwind

descartado

Definir colores y fuentes a criterio propio

El cliente ya había invertido en identidad visual — mi trabajo era implementarla con precisión, no reinventarla.

¿Cómo hacer rate limiting en Vercel serverless?

elegido

Contar rows por IP en Supabase en la última hora

descartado

In-memory Map

Las Vercel Functions son stateless — cada deploy es una instancia nueva. Un Map en memoria no persiste entre requests.

¿Usar middleware o verificación en cada route?

elegido

Proxy middleware que verifica Supabase Auth en cada request a /admin

descartado

Verificación manual en cada page

Un solo lugar de verdad para la auth. Si cambia la lógica, se cambia en un archivo.

Errores reales · lo que salió mal
01

createClient() a nivel módulo causaba 'supabaseUrl is required' en build time. Fix: moverlo dentro del handler.

02

Resend 403 porque usaba subdomain send.teciprestamos.com.ar en lugar del dominio raíz verificado.

03

Supabase Realtime no actualizaba porque faltaba setAuth(session.access_token) antes de suscribir al canal.

Qué mejoraría

Agregar un CMS headless para que el cliente edite las tasas y condiciones sin necesidad de código. Implementar WhatsApp Business API oficial para automatizar el seguimiento post-solicitud. Conectar con un CRM externo para escalar el pipeline.