Administra, organiza y haz crecer
tu escuela de artes marciales, baile y más.
Diseñé y desarrollé una aplicación móvil para ayudar a maestros y administradores a gestionar alumnos, asistencias y pagos de forma sencilla, rápida y desde cualquier lugar.
Así describió el dueño del Dojang el problema en nuestra primera conversación. No llegó pidiendo una app: llegó describiendo una operación que ya había crecido más allá de lo que una hoja de cálculo por instructor podía sostener.
El síntoma que más le costaba a la administración central no era ningún proceso individual, era la recopilación: juntar seis fuentes distintas cada vez que necesitaban dar seguimiento a un caso particular o armar un informe de rendimiento por escuela.
No hubo entrevistas formales con múltiples usuarios ni sesiones de investigación de agencia. El discovery fue directo: un cuestionario estructurado que Leonel, dueño de IDAR, respondió describiendo cómo opera su escuela hoy. Sus respuestas, no mis suposiciones, definieron el alcance del sistema.
Ese último punto (un evaluador externo sin cuenta fija en el sistema) no habría aparecido en ningún benchmark de competidores. Solo apareció porque se le preguntó directamente al dueño cómo funciona su escuela en la práctica.
No construí personas ficticias con biografías de agencia: construí perfiles a partir de necesidades reales que el sistema de roles y permisos tiene que resolver todos los días, verificadas directamente con el flujo de trabajo que describió el cliente.
El problema completo (alumnos, pagos, clases, cintas, exámenes, diplomas, informes) era demasiado grande para atacarlo de un solo golpe sin arriesgar meses de desarrollo sin nada usable. Prioricé junto con el cliente los dos procesos que generaban más fricción diaria: el control de asistencia y el seguimiento de pagos. No por coincidencia, eran los que más tiempo le costaban a la administración central de consolidar a mano cada mes.
La decisión de diseño más importante del proyecto: los padres de familia nunca instalan nada. Solo reciben un mensaje de WhatsApp con el comprobante. Toda la complejidad vive del lado del instructor.
El primer MVP funcionaba perfecto, pero se veía como cualquier tutorial de React Native: azul de Material Design por default, sin tipografía jerárquica, sin iconografía. Definí un sistema de tokens real (color, tipografía, radios, espaciado) y lo apliqué de vuelta al código, pantalla por pantalla.
Mismo layout, mismos datos, mismo código base: solo cambia el sistema de tokens aplicado. La diferencia es la que separa un tutorial de un producto.
Toca cualquier color para copiar su valor hex.
Diseñé 14 pantallas de alta fidelidad en Figma (incluyendo estados vacíos y de error, no solo el camino feliz) y las llevé directo a código: Expo (React Native) para la app, Supabase como backend con Row Level Security real, y un modelo de datos que creció de 3 tablas iniciales a 7 tablas relacionadas conforme el sistema de roles y el modelo de negocio se volvieron reales.
Dashboard: la pantalla que ve el instructor al abrir la app cada día.
Facturación CFDI sigue en el roadmap, pero no parte de cero: diseñé el portal de facturación CFDI de Salud Digna, así que entiendo el proceso de timbrado y los requisitos fiscales de primera mano. Para este piloto, sin embargo, el cliente pidió explícitamente algo más simple y urgente: ver más abajo.
Un fragmento real del componente de check-in, el estado de la máquina que gobierna las tres pantallas (escaneo, éxito, error) como un único flujo y no como pantallas sueltas:
"Pagos pendientes" ya existía como métrica desde el primer MVP, pero era solo un dato: no decía quién debía ni qué hacer al respecto. Este módulo lo convierte en una lista accionable: el sistema compara cada alumno contra los pagos registrados del mes actual y separa automáticamente quién está al día de quién no.
La lista de "Pendientes" real. Cada fila se resuelve en un toque: recordar o marcar pagado.
periodo: el mes que cubre, no solo la fecha en que se hizoperiodo = mes actualAl marcar un pago, el sistema genera un recibo en PDF con folio, fecha, concepto y monto, y lo comparte directo por WhatsApp en un solo paso, sin abrir dos veces la app de mensajería. El mismo mecanismo genera credenciales imprimibles por alumno: nombre, grupo, color de cinturón y su código QR de check-in, listas para que la escuela las mande a laminar.
La credencial física reutiliza el mismo QR que el check-in en pantalla: un solo identificador, dos formas de leerlo.
Dueño, administración, sensei y auxiliar ven la misma base de datos, pero nunca la misma información. Esto no se resuelve escondiendo botones en la pantalla: un botón oculto no protege nada si alguien puede llamar a la base de datos directamente. Se resuelve en el servidor, con Row Level Security de Postgres evaluando cada consulta según quién la hace.
Cada colaborador tiene un rol asignado desde que se une: el permiso real vive en el servidor, no en esta pantalla.
UPDATE o DELETE, Postgres no regresa error: regresa éxito con cero filas afectadasCada regla de negocio de este proyecto tuvo que traducirse en una decisión de arquitectura concreta, no solo en una nota de producto. "Administración no debe ver ingresos totales" se convirtió en una función de base de datos con validación de rol. "Tres grupos gratis, después se paga" se convirtió en un trigger de Postgres, no en un mensaje de la interfaz que cualquiera podría ignorar editando la petición directo a la API. Antes de ofrecer esto a una segunda escuela, necesitaba un plan free real. Definí los límites con la operación real del Dojang como referencia: su propia estructura de grupos fue el piso mínimo del plan gratuito, no un número arbitrario.
Los límites se aplican con triggers de Postgres, no con validaciones que el cliente pudiera saltarse editando la petición directo a la API. La interfaz solo avisa antes de que el límite truene: la protección real vive un nivel más abajo.
Academia Check-in Pro cuesta $249 MXN al mes por escuela, precio fijo sin importar cuántos alumnos tenga. No hay periodo de prueba: el plan Free es la prueba permanente. Si una escuela deja de pagar, nada se borra: regresa a Free, su primera sucursal sigue operando y las demás quedan en modo consulta.
Con el sistema base ya funcionando, el trabajo se volvió menos sobre arquitectura y más sobre fricción real de uso: cosas que solo aparecen cuando alguien que no eres tú, sin tu contexto, intenta dar de alta a un colaborador nuevo un martes en la noche.
Perfil de alumno real: foto, estado de cuenta con semáforo de días de atraso, e historial de asistencia.
La pieza más interesante de esta ronda fue el historial de asistencia con faltas reales, no solo asistencias. Estructurar el horario del grupo (días de la semana + hora, en vez de texto libre como "Lun/Mié 5pm") permitió calcular con precisión qué días tocaba clase y comparar contra los check-ins reales. Sin ese paso previo, "falta" era una palabra sin datos detrás.
Leonel intentó consultar el perfil de un alumno y le apareció "no se encontró este alumno", con la cuenta de dueño, que tiene todos los permisos. El error no era de permisos: era que su base de datos de producción no tenía las columnas que el código nuevo esperaba.
information_schema confirmó exactamente qué faltaba: dos columnas de horario, una tabla completa de invitaciones, dos funciones, y un bucket de StorageA diferencia de un prototipo en Figma, aquí hubo errores de sintaxis, cache corrupto, archivos que se sobrescribían entre sí, y navegación que fallaba silenciosamente. Documentar ese proceso, no solo el resultado, es parte de lo que hace este case study distinto.
Node desactualizado, versión de Expo Go incompatible con el SDK del proyecto, primer error resuelto antes de escribir una sola pantalla.
Modelo de datos inicial de tres tablas (alumnos, pagos, checkins) con relaciones, incluyendo el error clásico de URL mal copiada del dashboard.
Primera versión funcional, pero visualmente genérica: validó la arquitectura antes de invertir en diseño.
Tokens, tipografía, iconografía consistente. Una colisión de nombres de archivo rompió temporalmente la navegación completa de la app.
De una política abierta de desarrollo a cuatro roles con permisos evaluados en el servidor: incluyendo el hallazgo de que un DELETE bloqueado por RLS falla en silencio, sin error visible.
Triggers de Postgres que bloquean el alta de un cuarto grupo o un alumno 41 cuando el plan es gratuito: la restricción real, no solo un aviso en pantalla.
Un segundo proyecto de Supabase, migración completa de esquema, roles y políticas, y perfiles de build distintos en EAS, para que seguir desarrollando no arriesgue los datos reales del cliente.
APK instalable, base de datos limpia, cuatro cuentas reales (dueño, administración, sensei, auxiliar), en manos del cliente, no solo datos de prueba.
Onboarding de equipo sin depender de mí, foto y credencial con foto real, historial de asistencia con faltas calculadas, no solo asistencias.
Producción y desarrollo se desincronizaron en el esquema de base de datos. Diagnóstico, corrección, y una práctica nueva para que no se repita.
Migración a una base compartida con aislamiento por escuela vía Row Level Security. Dojang IDAR pasó a ser la primera escuela del sistema mientras su equipo seguía pasando lista todos los días.
Plan por escuela con fecha de vigencia y días de gracia, tarifas con recargo automático, reportes financieros, descarga de datos en CSV y eliminación de cuenta con periodo de gracia.
Landing pública con instalación guiada, aviso de privacidad y términos, SEO técnico y analítica de conversión para medir qué parte de la página lleva a descargar.
Con el piloto estable, la pregunta cambió de "¿le sirve a Leonel?" a "¿le serviría a una escuela que nunca he visto?". Eso obligó a revisar cada decisión que daba por hecho que el usuario era un Dojang de Taekwondo, y a resolver lo que un producto público necesita y un piloto no: cobrar, proteger datos y conseguir usuarios.
Funciones, planes Free y Pro, y la app para Android, en su sitio público.
El cliente describió síntomas ("cada sensei lleva su Excel"), no una solicitud de producto. Traducir esa frustración operativa en un alcance de sistema fue el primer trabajo de diseño, antes de dibujar una sola pantalla.
Priorizar recibo digital sobre CFDI, o multi-sede fuera del MVP, no fue una limitación técnica: fue foco deliberado en el dolor más urgente y en lo que el cliente pidió de verdad.
La app funcionaba perfecto antes de tener marca. La diferencia entre "funciona" y "se siente terminado" es completamente independiente de la lógica.
Que administración no vea el total de ingresos no es una restricción de la base de datos: es una decisión sobre qué información le corresponde a cada rol dentro del negocio real del cliente.
El cliente nunca escribió "no puedo usar la app". Fue un checkpoint estructurado, con preguntas concretas en el momento correcto, lo que sacó a la luz que parte de su equipo usa iPhone. Sin ese proceso, esa fricción hubiera quedado invisible indefinidamente.
Que un discovery real, aunque sea un solo cuestionario respondido por un solo dueño de negocio, vale más que cualquier plantilla de investigación genérica, porque las respuestas fueron específicas de un negocio real, no hipótesis mías sobre cómo "debería" operar una escuela.
No es una pantalla: es que el sistema de roles y el modelo de negocio siguen sosteniéndose bajo uso real, con datos reales, en manos de alguien que no soy yo. Eso solo se prueba entregando, no presentando.
No soy desarrollador de oficio, y este proyecto no cambió eso. Pero entrar al código, entender Row Level Security, escribir un trigger de Postgres, o depurar por qué un `DELETE` fallaba en silencio: eso sí cambió cómo diseño. Diseño mejor cuando entiendo las restricciones reales del sistema, no solo sus pantallas.