Plataforma de Reservas SaaS
Sistema de reservas online con pagos integrados para profesionales y pequeños negocios de servicios.
Cronología
3 Semanas
Rol
Full Stack Developer

El Problema
Muchos profesionales de servicios (clases, consultas, sesiones creativas) gestionan sus reservas de forma manual a través de WhatsApp, email o calendarios no sincronizados, lo que genera errores, pérdidas de tiempo y citas desaprovechadas.
- ✕Reservas desorganizadas entre múltiples canales.
- ✕Cancelaciones y no-shows sin control.
- ✕Falta de pagos anticipados o señalización.
- ✕Herramientas genéricas poco adaptadas a su flujo real.
La Solución
Diseñé y desarrollé una plataforma SaaS que centraliza la gestión de reservas, clientes y pagos en un único sistema, permitiendo a los profesionales automatizar su agenda y reducir fricción operativa.
Autenticación y Control de Acceso
Sistema de autenticación flexible y seguro que soporta múltiples métodos de acceso y separa claramente los roles de administradores, proveedores y clientes.
- Login con Google OAuth, Email/Password y Magic Links.
- Verificación OTP en registros por email.
- RBAC con portales diferenciados (Admin, Provider, Client).
- Protecciones activas contra abuso: rate limiting, CAPTCHA y honeypots.
Motor de Reservas Avanzado
Motor de reservas configurable que permite a los profesionales definir servicios, disponibilidad y reglas complejas sin fricción para el cliente final.
- Servicios flexibles: duración, precio, capacidad (1-on-1 o grupos).
- Disponibilidad híbrida con reglas semanales y excepciones por fecha.
- Buffers automáticos entre citas para evitar solapamientos.
- Gestión de concurrencia por servicio y límites globales.
Sincronización con Google Calendar
Sincronización bidireccional con Google Calendar para evitar dobles reservas y mantener la agenda siempre actualizada.
- Importación automática de eventos externos.
- Bloqueo de horarios ocupados en tiempo real.
- Actualización automática ante cancelaciones o reprogramaciones.
Pagos y Monetización Integrada
Sistema de pagos completo con Stripe que permite cobros anticipados, payouts automáticos y un modelo SaaS escalable.
- Pagos upfront para confirmar reservas.
- Stripe Connect Express para que cada proveedor cobre directamente.
- Soporte para comisiones de plataforma por transacción.
- Planes de suscripción mensual o anual para proveedores.
Gestión de Reservas Recurrentes
Soporte nativo para reservas periódicas, ideal para clases, terapias y servicios continuos.
- Configuración semanal o mensual.
- Generación automática de sesiones futuras.
- Gestión centralizada de cancelaciones y cambios.
Internacionalización (i18n)
Plataforma preparada para audiencias internacionales con soporte completo multi-idioma.
- Interfaz totalmente traducida a inglés y español.
- Detección automática de idioma mediante middleware.
- Emails y mensajes de error localizados.
Automatización y Notificaciones
Sistema de automatización que reduce tareas manuales y mantiene informados a clientes y proveedores.
- Recordatorios automáticos 24h y 1h antes de la cita.
- Emails transaccionales para confirmaciones y cancelaciones.
- Cron jobs ejecutados de forma serverless.
Analíticas y Panel de Control
Dashboard interactivo para que los proveedores entiendan el rendimiento de su negocio.
- Métricas de ingresos y volumen de reservas.
- Servicios más populares.
- Visualizaciones claras mediante gráficos interactivos.
Stack Tecnológico
Next.js 14
Framework
TypeScript
Language
PostgreSQL
Database
Prisma
ORM
Auth.js
Auth
Stripe Connect
Payments
Resend
TailwindCSS
Styling
Shadcn/UI
UI
Zod
Validation
React Hook Form
Forms
next-intl
i18n
Retos Técnicos
Handling Webhook Idempotency
Asegurar que los webhooks de Stripe se procesen exactamente una vez. Retries de red podían causar registros duplicados si no se manejaban correctamente.
const handleWebhook = async (req, res) => {
const event = req.body;
// 1. Check Redis for Idempotency Key
const isProcessed = await redis.get(event.id);
if (isProcessed) {
return res.status(200).send("Already processed");
}
// 2. Process Business Logic
try {
if (event.type === 'invoice.paid') {
await updateInvoiceStatus(event.data.object);
}
// 3. Mark as processed for 24h
await redis.set(event.id, 'processed', 'EX', 86400);
res.json({ received: true });
} catch (err) {
console.error(err);
res.status(500).send();
}
};