~ / portfolio / projects / flacow.md — main
cd .. · volver al portafolioback to portfolio
~/ projects/ flacow.md

#Flacow

App para registrar tu progreso en el gimnasio y lograr tus objetivos de fuerza.App to track your gym progress and hit your strength goals.

role:"full-stack"
year:2024
status:"live"
ReactNestJSMaterialUIPostgreSQLJWTDocker
🔒flacow.bfmu.dev
Flacow cover
bash · clone repo
$ git clone https://github.com/redflox/progresapp-flacow

##overview

Flacow es una aplicación web full-stack para registrar tus entrenamientos. Querías ver si esa serie de press banca de hoy fue mejor que la de hace 6 semanas — pues lo ves de un vistazo, en una gráfica, sin abrir cinco pestañas ni rascar un Excel.Flacow is a full-stack web app for logging workouts. You want to know whether today's bench press set was better than the one six weeks ago — you see it at a glance, in a chart, without opening five tabs or wrestling a spreadsheet.

Construido como side-project, vive en producción en flacow.bfmu.dev y usa una arquitectura monorepo con frontend en React + MaterialUI y backend en NestJS.Built as a side-project, it runs in production at flacow.bfmu.dev with a monorepo architecture: React + MaterialUI on the frontend, NestJS on the backend.

##context

Llevo varios años entrenando con foco en progresión de carga. La rutina pide saber cuánto levantaste la sesión anterior, en cuántas series, con qué RPE. Probé un par de apps populares y todas fallaban en lo mismo: UX pensada para casual fitness, no para fuerza; imposible ver tendencias por ejercicio sin pagar premium; captura de series lenta — 6 taps para registrar un set.I've been training with a focus on progressive overload for a few years. The routine demands knowing what you lifted last session, how many sets, at what RPE. I tried a couple of popular apps and they all failed at the same things: UX built for casual fitness, not strength training; impossible to see per-exercise trends without going premium; slow set capture — 6 taps to log a single set.

Si una herramienta hace fricción justo en el momento en que la necesitás, dejás de usarla. Y un tracker que no usás no sirve.If a tool creates friction at the exact moment you need it, you stop using it. And a tracker you don't use is no tracker at all.

##architecture

### Monorepo con apps separadasMonorepo with split apps

Frontend y backend viven en el mismo repo pero como paquetes independientes. Comparten un paquete shared/ con tipos TypeScript de los DTOs — un cambio en el contrato compila en ambos lados o explota el build.Frontend and backend live in the same repo but as independent packages. They share a shared/ package with TypeScript types for DTOs — a contract change either compiles on both sides or breaks the build.

### Modelo de datos por sesiónSession-based data model

En vez de modelar 'sets' sueltos, todo cuelga de una WorkoutSession. Esto hizo que las queries de progreso sean joins rápidos en lugar de subqueries de agregación cara.Instead of modeling loose 'sets', everything hangs off a WorkoutSession. This turned progress queries into fast joins rather than expensive aggregation subqueries.

### Auth con refresh rotationAuth with refresh rotation

Cada refresh emite un nuevo par y revoca el anterior. Si alguien usa un refresh ya canjeado, todos los tokens del usuario se invalidan — heurística simple para detectar robo de token.Each refresh issues a new pair and revokes the previous. If anyone uses a refresh that's already been redeemed, all of the user's tokens are invalidated — simple heuristic to flag token theft.

##challenges

  1. Capturar series rápido sin teclado. Diseñé inputs con steppers + presets de pesos comunes. De 6 taps por set bajé a 2. Logging sets fast without a keyboard. I designed steppers + common-weight presets. Went from 6 taps per set down to 2.
  2. Offline en gimnasios con WiFi roto. Service worker + queue de sincronización. La app graba localmente y sincroniza al volver señal. Offline in gyms with broken WiFi. Service worker + sync queue. The app records locally and syncs when signal returns.
  3. Gráficas de progreso que no mientan. Hubo que decidir cómo mostrar 'mejor set' vs 'volumen total' — terminé exponiendo ambas con un toggle, en lugar de elegir por el usuario. Progress charts that don't lie. Had to decide how to surface 'top set' vs 'total volume' — ended up exposing both with a toggle instead of choosing for the user.

##learnings

  • Construir para vos mismo es el mejor product brief. Cada decisión tiene un usuario real (yo) probando en el gimnasio. Building for yourself is the best product brief. Every decision has a real user (me) testing in the gym.
  • NestJS escaló mejor de lo que esperaba para un side-project. La modularización por feature compensa el boilerplate inicial. NestJS scaled better than expected for a side-project. Feature-based modularization pays for the initial boilerplate.
  • La parte difícil de un tracker no es guardar datos — es mostrarlos en el momento justo. Pasé más tiempo en UX de gráficas que en el modelo de datos. The hard part of a tracker isn't storing data — it's surfacing it at the right moment. I spent more time on chart UX than on the data model.

##roadmap

  • MVP de logging y dashboardLogging & dashboard MVP
  • Auth con refresh rotationAuth with refresh rotation
  • Modo offline básicoBasic offline mode
  • Plantillas de rutina (5/3/1, PPL, etc.)Routine templates (5/3/1, PPL, etc.)
  • Exportar histórico a CSVExport history to CSV
  • Compartir progreso público (read-only links)Public progress sharing (read-only links)
  • App móvil nativa con React NativeNative mobile app with React Native

flacow.bfmu.devapp en vivolive app
github.com/redflox/progresapp-flacowcódigo fuentesource code


volver al portafolioback to portfolio $ git log flacow