Bohemian Gym
Resumen
Bohemian Gym es una app de entrenamiento para atletas y gimnasios. El atleta arma sus rutinas y la app conduce la sesión mientras ocurre (rounds de combate, campana de descanso con audio ducking, recuperación de sesión, RPE retroactivo) y convierte el historial en recomendaciones de sobrecarga progresiva. Cada gimnasio recibe builds white-label, roles propios y un flujo entrenador-atleta. Sale en 5 flavors de Flutter (atleta, entrenador, manager, consumidor y consola) sobre un core offline-first compartido, con una API NestJS 11 + MongoDB y un asistente con Gemini.
Puntos clave
Sesiones que conduce la appEjecución de la sesión en tiempo real como diferencial frente a apps que son un Excel con UI
Conduzco la sesión de entrenamiento desde la app: rounds de combate con timer de descanso, campana en background con audio ducking y un modelo PendingSet para el seguimiento en curso. Strong, Hevy y Jefit registran cuando el entrenamiento ya pasó.
Sin datos perdidos al interrumpirContinuidad sin pérdida de datos ante interrupción, background o crash
Recuperé sesiones interrumpidas con snapshot del cubit y restoreFromSnapshot: la sesión no pierde datos y el usuario sigue donde quedó.
Cinco flavors, white-label por gimnasio5 flavors desde 1 codebase con builds white-label por gimnasio
Sirvo 5 flavors (atleta, entrenador, manager, consumidor y consola) desde un solo monorepo Flutter, con builds white-label por gimnasio (slug del gimnasio mapeado a applicationId / bundle id) y roles que cada gimnasio define con role bindings y audiencias por app.
Flujo de invitación coach-atletaFlujo entrenador-atleta entregado sobre códigos de invitación
Habilité la colaboración entrenador-atleta con códigos de invitación y flujo de asignación (aceptar, rechazar, revocar, pendiente), tablero de asignación de rutinas y librería compartida de ejercicios y sistemas.
Auth y sync endurecidosSeguridad de nivel productivo y sync v2 resiliente offline
Endurecí la autenticación y la sincronización de datos para producción: hash de password en cliente, rotación de refresh con detección de reuso, backup por snapshot, detección de drift y UI de resolución de conflictos.
Asistente de IA endurecidoAsistente IA en producto endurecido, tasa de ataque verificada en 0%
Embebí un asistente IA sobre Gemini en la app (Assistant v2) con chat polimórfico, controles de presupuesto y 7 capas de defensa contra prompt injection (0% ASR en el baseline del benchmark Spikee).
Motor de sobrecarga progresivaMotor de sobrecarga progresiva, ausente en las apps de solo registro
Construí la inteligencia de sobrecarga progresiva: rastrea las métricas de levantamiento entre sesiones y recomienda ajustes de peso y repeticiones según el historial de volumen e intensidad. El atleta deja de adivinar.
API NestJS 11 sobre MongoDB13 módulos de negocio, 45 archivos spec con cerca de 470 casos Jest, y tests de integración con Supertest y mongodb-memory-server
Construí la API en NestJS 11 + MongoDB (Mongoose): login con JWT y con Google, throttling, Swagger, trazas con OpenTelemetry y un asistente Gemini que transmite por SSE con modelos de respaldo y presupuesto de tokens. Se despliega como imagen Docker en bohemian.accentio.dev con Statio, mi propia herramienta de deploy.
Marionette en los cinco flavorsUn agente MCP maneja los 5 flavors en builds de debug
Conecté un binding de Marionette en los builds de debug de los 5 flavors, fuera del release por tree-shaking, y una config que le enseña al driver los componentes del design system, para que un agente MCP lea la etiqueta de cada botón en lugar de un nodo vacío.
Guía de código cerrada con tests20 tests de arquitectura corren con la suite
Escribí la guía de código del proyecto (un CLAUDE.md de 2.300 líneas) y la trabé con 20 tests de arquitectura, como la pureza de imports del design system y el grafo de imports de la consola.
CI hacia Firebase App DistributionCerca de 1360 casos de test Flutter en 158 archivos
Publico la app con GitHub Actions y Fastlane en Firebase App Distribution: la llave de firma sale de GCP Secret Manager por OIDC y el pipeline verifica el firmante del APK.