← Volver a proyectos

Vital

Full-stack · sistema end-to-end en producción (backend, panel y PWA)
Control de acceso físico real: un servicio liviano sin interfaz lee el molinete por Arduino (serialport), valida la membresía activa contra la API y abre la puerta — todo event-driven sobre NestJS
Cumplimiento fiscal argentino de punta a punta: facturación electrónica AFIP (SOAP), cobros con Mercado Pago y un bot de WhatsApp para emitir facturas por chat desde el celular
Cobranza automática (dunning) por cron con escalado: reintentos → avisos por email/SMS → período de gracia → suspensión; más una PWA de socios con rutinas, registro de series y récords personales

Gimnasio familiar · Sistema en producción · Argentina

El gimnasio de mi familia corriendo sobre un solo sistema: el socio entra pasando su credencial por el molinete, paga y factura sin fricción, y entrena con su rutina en el celular. Tres aplicaciones, una misma fuente de verdad.

Activo Por vencer Vencido semáforo de membresías — el ancla de toda la operación
Inicio de la app del socio: saludo, estado de membresía y botón para empezar el entrenamiento

¿Qué problema resuelve Vital?

Vital es el gimnasio de mi familia. Como todo gimnasio de barrio que crece, durante años se manejó con una mezcla de planilla de Excel, un cuaderno en la recepción y grupos de WhatsApp. Con varios cientos de socios activos, esa forma de trabajar ya no daba: nadie sabía con certeza quién tenía la cuota al día, la puerta la abría alguien a ojo, la facturación era un trámite manual a fin de mes y el socio no tenía ninguna herramienta propia más allá de mensajear al profe.

Lo construí para nuestra operación real, con un solo sistema que cubre las tres caras del negocio a la vez: la operación de la recepción (quién entra, quién debe, quién se anota), el cumplimiento fiscal (cobros y facturas de verdad, con AFIP y Mercado Pago) y la experiencia del socio (su rutina, su progreso, su acceso). El desafío no era ninguna de esas piezas por separado, sino que convivieran sobre un mismo modelo de datos sin duplicar la verdad.

¿Cómo está construido Vital?

Lo armé como un monorepo con tres aplicaciones independientes que comparten una única API. En el centro, un backend en NestJS con PostgreSQL y Prisma, diseñado event-driven: los módulos no se llaman entre sí a mano, emiten eventos y otros reaccionan. Cuando el molinete lee una credencial, eso dispara una cadena —verificar acceso → registrar asistencia → notificar— sin acoplar el hardware a la lógica de negocio.

gestion-backend NestJS · PostgreSQL · Prisma · EventEmitter
gestion-frontendPanel admin · React + MUI
gestion-pwaApp de socios · Capacitor (iOS/Android)
landingSitio público · captación
Molinete + Arduinoservicio liviano sin interfaz → puerto serie → API
Mercado PagoAFIPTwilio / WhatsAppFirebase Push

Cada superficie tiene un usuario y un propósito distinto, pero todas hablan con la misma API. Esa fue la decisión estructural que sostiene el resto: una sola fuente de verdad para membresías, pagos, asistencias y rutinas.

Pantalla de Recepción del panel: buscador de ingreso, alertas de membresías vencidas y por vencer, asistencia y pagos del día
Recepción — el home operativo del panel: no es un dashboard, es una bandeja de tareas (vencidos, por vencer, ingresos y pagos de hoy).

¿Qué decisiones técnicas sostienen Vital?

Las partes que más me importan de Vital no son las pantallas, son los sistemas que las conectan con el mundo físico y con la AFIP.

Hardware + software

El molinete que sabe quién sos

El acceso no es un botón: es hardware real. Un servicio liviano sin interfaz se comunica por puerto serie (serialport) con un Arduino que controla el molinete. Cuando alguien pasa la credencial, el sistema valida contra la API si la membresía está activa y solo entonces abre la puerta — sin una aplicación de escritorio de por medio.

  • Lectura de credencial vía Arduino → evento en NestJS → verificación de acceso desacoplada del hardware
  • Check-in alternativo por QR: tokens de un solo uso con expiración a los 5 minutos, generados desde la app del socio
  • Cada ingreso queda registrado como asistencia y dispara notificaciones sin bloquear la puerta
Cumplimiento fiscal

Cobrar y facturar de verdad, en Argentina

Un gimnasio que factura en serio necesita hablar con la AFIP y con un medio de pago. Vital integra facturación electrónica contra la AFIP por SOAP (con manejo de certificados) y cobros con Mercado Pago, incluyendo webhooks idempotentes para no procesar dos veces el mismo pago.

  • Facturación electrónica AFIP con validación de certificados y diagnóstico propio
  • Pagos con Mercado Pago y una tabla de webhooks procesados para garantizar idempotencia
  • Un bot de WhatsApp (vía Twilio) que le permite al staff emitir facturas conversando desde el celular, con una máquina de estados por sesión
Listado de facturas con número de comprobante, fecha, cliente, total y estado (Generada, Compartida, Pagada)
Facturas — comprobantes con su estado (generada → compartida → pagada) sobre la facturación electrónica de AFIP.
Cobranza sin intervención

La deuda se persigue sola

La plata que se pierde en un gimnasio casi siempre es plata que nadie fue a cobrar. Por eso la cobranza (dunning) es un subsistema propio que corre por cron y escala solo: primero reintenta, después avisa, después da gracia y finalmente suspende — sin que nadie tenga que acordarse.

  • Scheduler con tres etapas: procesar reintentos → enviar avisos (email/SMS) → suspender al vencer la gracia
  • Semáforo de membresías (activo / por vencer / vencido) como estado central de toda la app
  • Notificaciones multicanal: email (SMTP), SMS (Twilio) y push (Firebase) según el evento
La app del socio

Entrenar, no solo pagar

La PWA de socios —empaquetada con Capacitor para iOS y Android— es lo que hace que el sistema no sea solo administrativo. El socio ve su rutina asignada, la ejecuta bloque por bloque y registra cada serie; el sistema le lleva el historial y le detecta récords personales.

  • Catálogo público de rutinas + asignaciones por socio o por grupo, con días, bloques y ejercicios
  • Registro de sesiones de entrenamiento: series, cargas y récords personales automáticos
  • Reserva de clases, métricas de salud, check-in por QR y notificaciones push
Catálogo de rutinas en el panel: Full Body Principiante, Push Pull Legs, Upper/Lower y planes personalizados con su cantidad de ejercicios
El staff arma el catálogo de rutinas en el panel; el socio la ejecuta en su celular.
Detalle de rutina en la app: bloque principal con ejercicios, series, repeticiones y descanso
La rutina, bloque por bloque
Pantalla de progreso: kilos levantados en total, entrenamientos, horas, récords personales y asistencia reciente
Progreso: volumen, entrenos y PRs
Pantalla de ingreso por QR con temporizador de caducidad a los 5 minutos
Check-in por QR, con caducidad a los 5 min

Las tres superficies

Panel admin

React 19 + MUI para la recepción. Diseñado como bandeja de tareas, no como dashboard: check-in con ⌘K, cobros y estado de membresías con acciones directas en cada fila.

App de socios

PWA con Capacitor: rutinas, progreso, clases y acceso por QR, publicable en las tiendas como app nativa.

API central + acceso

NestJS event-driven sobre PostgreSQL/Prisma. Una sola fuente de verdad para las superficies, las integraciones externas y el molinete por serie — sin capas de más.

Cierre

Vital es el proyecto donde más se nota lo que significa llevar algo de punta a punta: no termina en una pantalla bonita, termina en un molinete que se abre, en una factura válida ante la AFIP y en un socio anotando su serie desde el celular. Tres aplicaciones, un modelo de datos, y un montón de decisiones —event-driven, idempotencia de pagos, cobranza automática, hardware por serie— que existen porque el sistema corre en el gimnasio de mi familia todos los días. Incluso el control de acceso terminó siendo un servicio mínimo: la primera versión fue una app de escritorio que resultó ser de más, y quedó reemplazada por algo mucho más chico que hace exactamente lo necesario.