SaaS Multi-Tenant · Sistema de Turnos

Bowtify
Cómo funciona

Una plataforma SaaS multi-tenant para gestión de turnos, historia clínica, e-commerce y finanzas, diseñada para profesionales de la salud y servicios.

3
Apps (Web, API, Mobile)
12
API Endpoints grupos
Tenants soportados
15+
Módulos del sistema

Stack en capas

Monorepo con tres aplicaciones independientes que comparten código a través de paquetes compartidos.

👤 Clientes / Usuarios
🌐 Cliente Web (Browser)
📱 App Mobile (React Native / Expo)
🔔 Push Notifications
🖥️ Frontend — Next.js 15
🏠 Landing SaaS (turnero.com)
🏷️ Portal del Tenant (/{slug})
🛡️ SuperAdmin Panel
⚙️ Middleware (tenant resolver)
⚡ Backend — Express.js + TypeScript
🔐 Auth JWT
📅 Booking Engine
🛒 E-commerce
💊 Historia Clínica
💰 Finanzas
🏢 Tenant Management
🗄️ Base de Datos — PostgreSQL + Prisma ORM
🐘 PostgreSQL (RLS)
🔑 Aislamiento por tenant_id
💳 MercadoPago Webhooks

Un sistema, múltiples negocios

Cada empresa tiene su propio subdominio, branding y datos completamente aislados.

🏥 Clinica Sur
clinica-sur.turnero.com
Slugclinica-sur
Brand color#6C63FF
PlanPro
Turnos activos✓ Aislados
Pacientes✓ Privados
💇 Estética Zen
estetica-zen.turnero.com
Slugestetica-zen
Brand color#00D4AA
PlanStarter
Turnos activos✓ Aislados
Clientes✓ Privados
🦷 OdontoPlus
odonto-plus.turnero.com
Slugodonto-plus
Brand color#FFB347
PlanEnterprise
Turnos activos✓ Aislados
Historia clínica✓ Privada
🔍 Cómo el Middleware resuelve el Tenant
Llega el request
Browser solicita clinica-sur.turnero.com/booking
Middleware detecta subdominio
Extrae clinica-sur del hostname y reescribe la URL a /clinica-sur/booking
Next.js route [tenant]
La ruta dinámica /app/[tenant]/page.tsx recibe el slug
API valida tenant
El header x-tenant-slug: clinica-sur viaja en cada request. El middleware requireTenant busca en DB e inyecta req.tenant
Datos 100% aislados
Todos los queries de Prisma incluyen where: { tenant_id: req.tenant.id }

Cómo fluye la experiencia

Cuatro flujos clave que cubren el ciclo completo del usuario.

📅
Reserva de Turno
1
Cliente visita tenant.turnero.com y ve servicios disponibles
2
Selecciona especialidad → profesional → servicio
3
Elige horario disponible (slots calculados según agenda del profesional)
4
Se registra / loguea como Customer
5
Confirma turno → recibe ticket PDF con QR
6
Notificación por email al cliente y al profesional
🏢
Panel de Administración
1
Admin loguea en /{tenant}/admin con JWT
2
Ve agenda del día: turnos, estados, profesionales
3
Gestiona profesionales, servicios, especialidades
4
Accede a historia clínica de cada paciente
5
Monitorea finanzas: ingresos vs gastos
6
Configura branding, logo y color de marca
🛒
Tienda Online
1
Tenant crea productos con stock, precio e imagen
2
Cliente visita /{tenant}/tienda
3
Agrega productos al carrito
4
Checkout: pago vía MercadoPago o manual
5
Admin recibe pedido y gestiona el estado
6
Cliente ve sus pedidos en /mis-pedidos
🚀
Alta de nuevo negocio
1
Negocio visita turnero.com y elige un plan
2
Se registra en /register con datos del negocio
3
Se crea el Tenant + Subscripción (trial)
4
Recibe su URL propia: mi-negocio.turnero.com
5
Configura profesionales, servicios y horarios
6
Activa pago con MercadoPago o manual

Tecnologías elegidas

Cada herramienta fue seleccionada para garantizar escalabilidad, velocidad de desarrollo y robustez.

Next.js 15
Frontend Web · App Router
Express.js
Backend API · TypeScript
📱
Expo / React Native
App Mobile (profesionales)
🐘
PostgreSQL
Base de datos relacional
🔷
Prisma ORM
Modelos + migraciones
🔑
JWT Auth
Autenticación stateless
💳
MercadoPago
Pagos + suscripciones
📧
Email Notif.
Confirmaciones de turno
🐳
Docker
Contenedores por app
☸️
Helm / Kubernetes
Deploy en cloud
📦
NPM Workspaces
Monorepo management
🔔
Expo Push
Notif. a profesionales

Base de datos multi-tenant

Todas las entidades de negocio están vinculadas al tenant_id para aislamiento total.

🏢 Tenant
slug — URL única
brand_color — Branding
settings_json — Config
status — active/suspended
📋 Plan + Subscription
price — Mensual/anual
features_json — Capacidades
status — trial/active/cancelled
mp_subscription_id
👨‍⚕️ Professional
specialty_id — Especialidad
working_hours_json — Agenda
expo_push_token — Push notif
avatar_url — Foto
🔧 Service
duration_minutes
price — Opcional
specialty_id — FK
📅 Appointment
start_time / end_time
status — pending/confirmed
qr_code_hash — Ticket único
notes — Notas clínicas
👤 Customer
email — Único por tenant
google_id — OAuth
medical_notes
appointments[]
📦 Product + Order
stock — Inventario
mp_preference_id
payment_method — MP/manual
items[] — OrderItem
💊 Historia Clínica
PatientFile — Imágenes/PDF
ClinicalQuestion — Formularios
PatientAnswer — Respuestas
💰 Expense
amount — Monto
category — RRHH/insumos…
date — Fecha del gasto

Funcionalidades completas

Cada módulo es independiente y puede activarse por tenant. Así lucen en producción.

💳
Pagos MercadoPago
Preferencias, webhooks, suscripciones
🔔
Notificaciones Push
Expo Push para profesionales
📧
Emails Automáticos
Confirmación y recordatorio de turno
🎨
Branding por Tenant
Logo, color, hero image, tagline
🛡️
SuperAdmin
Gestión global de tenants y planes
🔐
Auth multi-rol
SuperAdmin / TenantAdmin / Staff / Customer
📱
App Mobile
App para profesionales (React Native)
🗺️
Multi-dominio
Subdominio o path por tenant
⚙️
Settings avanzados
Instrucciones de pago manual, config JSON

Pipeline de deploy

Desde el código fuente hasta producción, completamente containerizado.

💻
Código
Fuente
🐙
GitHub
Actions
🐳
Docker
Build
☸️
Helm
Chart
🌐
bowtielabs
.cloud
🌐 apps/web
• Next.js 15 + App Router
• Puerto 3000
• Middleware proxy → API
• Dockerfile multi-stage
⚡ apps/api
• Express.js + TypeScript
• Puerto 4000
• Uploads estáticos /uploads
• Dockerfile multi-stage
📱 apps/mobile
• Expo + React Native
• App para profesionales
• Nginx como web server
• Docker + nginx.conf