Petzara empezó con una observación simple: petshops que atienden bien, pero se traban en la operación manual. La agenda en un cuaderno, el historial de los clientes en WhatsApp, un equipo sin visibilidad. El problema era claro. La solución tenía que construirse.
¿Por qué un SaaS y no una app?
La primera decisión fue elegir la web en lugar de una app nativa. El motivo: los petshops usan múltiples dispositivos — la computadora de la recepción, el celular del peluquero, la tableta del gerente. Un sistema web responsivo resuelve eso sin la sobrecarga de dos codebases.
Además, la web tiene deploy instantáneo. Actualizar un sistema web es invisible para el usuario. Actualizar una app nativa exige aprobación en las tiendas y que el usuario actualice manualmente.
La decisión más difícil: modelar la agenda
El corazón de Petzara es el sistema de citas. Y tiene que ser confiable — dos citas en el mismo horario con el mismo peluquero es un error grave que perjudica al cliente y a la empresa.
La solución no fue solo la validación en el front-end. La base de datos tiene una constraint que impide físicamente dos citas en conflicto. La validación en el front-end existe para dar feedback inmediato; la de la base de datos existe como garantía final.
-- Constraint que impede conflitos de horário por funcionário
CREATE UNIQUE INDEX unique_appointment_slot
ON appointments (employee_id, date, time_slot)
WHERE status != 'cancelled';
El desafío del calendario
Implementar un calendario interactivo desde cero es complejo. Usamos FullCalendar, pero la integración con nuestro modelo de datos exigió una personalización significativa.
El calendario necesitaba:
- Mostrar las citas en tiempo real (WebSocket)
- Filtrar por empleado con colores distintos
- Permitir arrastrar citas entre horarios
- Funcionar bien en el celular (el principal dispositivo de uso)
El drag-and-drop en móvil fue lo más trabajoso — los eventos táctiles se comportan distinto que los del mouse en los calendarios. La solución fue una capa de abstracción que mapea los eventos táctiles a drag events.
Notificaciones: lo que parecía simple
Enviar un WhatsApp de confirmación de cita parece simple. En la práctica, implica:
1. Una cola de mensajes para no sobrecargar la API 2. Rate limiting por número de teléfono 3. Reintento en caso de falla 4. Registro de los mensajes enviados 5. Opt-out para los clientes que no quieren recibirlos
Lo que empezó como "manda un mensaje" se convirtió en un microservicio propio.
Lo que aprendimos de los primeros usuarios
Los petshops que lo usaron en las primeras semanas mostraron algo inesperado: la funcionalidad más usada no era la agenda — era el historial de la mascota.
"¿Qué producto usé la última vez con Buddy?" "¿Este perro tiene alergia a algún producto?" "¿Cuánto tiempo toma arreglarlo?"
Eso nos hizo priorizar el registro de mascotas con campos de observaciones, historial de servicios e incluso carga de fotos. El producto mejoró gracias al uso real, no a la planificación.
Stack final
- Front-end: React + TypeScript + Tailwind CSS
- Back-end: Node.js + Express
- Base de datos: PostgreSQL con Prisma ORM
- Tiempo real: WebSocket para las actualizaciones de la agenda
- Notificaciones: WhatsApp Business API + cola Redis
- Deploy: Vercel (front-end) + Railway (back-end + base de datos)
- Pagos: Stripe para suscripciones mensuales
Qué haría diferente
Si empezara hoy, usaría Next.js con App Router desde el principio para tener SSR y SEO sin configuración extra. También implementaría multi-tenancy a nivel de base de datos (un schema por tenant) en lugar de row-level security, que complica las queries.
Pero esas son mejoras de arquitectura. El núcleo del producto — resolver el problema de las citas de los petshops — funciona bien y está en uso real.
Eso es lo que importa.