
Inicio
Portada con partículas y accesos rápidos. Destaca la lista en la que el músico está asignado.
lista-propia:ver
Caso de estudio · Sistema full‑stack en producción
Una PWA para que un ministerio de música organice su repertorio, arme las listas de cada culto, asigne al equipo y toque con letras, acordes y audio, desde el celular y con permisos por rol.
Cielos Abiertos nació de una necesidad concreta: el equipo de música de una iglesia coordinaba todo por WhatsApp, PDFs sueltos y memoria. El sistema reemplaza ese circuito sin cambiar la forma en que el equipo ya trabaja.
El líder armaba la lista de cada domingo escribiéndola a mano en un chat. Letras y acordes vivían en archivos distintos, cada músico en un tono diferente y nadie sabía con certeza quién tocaba qué.
Un único lugar, usable desde el celular durante el ensayo y el culto, donde la lista, el equipo, la letra, los acordes y el audio estén a un toque, con visibilidad según el rol de cada persona.
Usuarios no técnicos, mayormente en celular (incluido iPhone) y con conexión irregular dentro del templo.
Un sistema de 17 tablas, 9 módulos y 36 permisos que el equipo usa cada semana, con un flujo de trabajo guiado por su propia forma de organizarse (tres alabanzas, dos adoraciones y la ofrenda).
Relevados con los propios líderes y refinados en iteraciones cortas. Cada uno es verificable.
| ID | Requisito | Tipo | Prioridad |
|---|---|---|---|
| RF-01 | Alta, edición y baja de canciones con tipo (alabanza/adoración), tono, BPM, etiquetas, links y letra con acordes. | Funcional | Alta |
| RF-02 | Buscar y filtrar el repertorio por título, artista, tipo, etiqueta y tono. | Funcional | Alta |
| RF-03 | Crear listas por fecha con secciones (alabanza, adoración, ofrenda), tono propio por canción y reordenamiento. | Funcional | Alta |
| RF-04 | Asignar al equipo por instrumento, solo entre quienes pueden tocarlo. | Funcional | Alta |
| RF-05 | Generar una lista aleatoria (3 alabanzas + 2 adoraciones + ofrenda) respetando temas y canciones enganchadas. | Funcional | Media |
| RF-06 | Ver letra y acordes, transponer de tono y exportar a PDF. | Funcional | Alta |
| RF-07 | Reproductor con audio propio (pistas) o video de YouTube, con repetir tramo y cola. | Funcional | Media |
| RF-08 | Copiar la lista, el equipo y las notas con el formato que usan los líderes en WhatsApp. | Funcional | Alta |
| RF-09 | Cada músico ve destacada la lista en la que está asignado. | Funcional | Media |
| RF-10 | Estadísticas de uso: canciones más tocadas, rotación y búsqueda en el historial. | Funcional | Baja |
| RF-11 | Gestión de usuarios y roles; los roles y sus permisos se editan desde la propia aplicación. | Funcional | Alta |
| RF-12 | Acceso de invitado de solo lectura, sin crear cuenta. | Funcional | Media |
| RNF-01 | Seguridad: contraseñas con hash, JWT, permisos verificados en el servidor en cada petición. | No funcional | Alta |
| RNF-02 | Usabilidad móvil: sin desbordes entre 320 y 430 px, targets táctiles amplios, instalable como app. | No funcional | Alta |
| RNF-03 | Rendimiento: carga inicial renderizada en servidor, listas paginadas y caché de consultas. | No funcional | Media |
| RNF-04 | Costo operativo mínimo: corre en planes gratuitos con mitigación del “arranque en frío”. | No funcional | Alta |
| RNF-05 | Mantenibilidad: módulos por dominio, tipado estricto, tests y CI obligatorio antes de integrar. | No funcional | Alta |
| RNF-06 | Trazabilidad: auditoría de creación y modificación y baja lógica de datos. | No funcional | Media |
Delimitar lo que NO se hace fue tan importante como lo que sí: mantiene el producto chico y mantenible.
Evolución natural: multi‑tenant y notificaciones, sin cambiar el modelo de permisos.
Filtrá por actor y mirá qué puede hacer cada uno. Cada caso está atado a un permiso del sistema.
Busca y filtra las canciones del ministerio.
Crea, edita y da de baja canciones, con tags, links y pistas.
Abre la canción, transpone y fija el tamaño de letra.
Exporta la canción o la lista completa con acordes.
Escucha la pista o el video, repite un tramo y arma cola.
Elige fecha, secciones, canciones y tono de cada una.
Sorteo ponderado 3+2+ofrenda respetando temas.
Elige músicos por instrumento según lo que sepan tocar.
Copia lista, equipo y notas con el formato del grupo.
Ve destacada la lista donde está en el equipo.
Guarda y reutiliza plantillas de estructura.
Guarda canciones para encontrarlas rápido.
Más tocadas, rotación y búsqueda en el historial.
Alta, baja lógica y asignación de roles e instrumentos.
Define qué puede hacer cada rol, sin tocar código.
Accede de solo lectura sin crear cuenta.
Cliente y API desacoplados, desplegados por separado. Tocá cada bloque para ver su responsabilidad.
Modelo de dominio. Los rombos marcan composición (el hijo no existe sin el padre); las flechas, asociaciones. Pasá el mouse sobre una clase para aislar sus relaciones.
Dos flujos clave en carriles: quién hace cada paso. Podés animar el recorrido.
Organización por funcionalidad (feature‑first) en ambos lados: lo que cambia junto vive junto.
Controlador recibe y valida, servicio decide, repositorio persiste. Sin lógica de negocio en controladores ni componentes de página.
Generador de listas, parser de acordes, armado de mensajes de WhatsApp y estados de lista son funciones puras en lib/, testeables sin UI.
DTOs con class‑validator en la API y tipos compartidos en el cliente; los permisos son strings tipados recurso:acción.
Qué se eligió, por qué y qué se resignó. Formato de registro de decisiones (ADR).
Los líderes querían decidir quién ve qué sin pedir cambios al desarrollador.
Permisos recurso:acción persistidos por rol y leídos de la BD en cada petición; roles editables desde la UI.
Cambios inmediatos y sin redeploy. Costo: una consulta extra por request, mitigada con índices.
Se necesitaba una API reutilizable y un cliente con buena carga inicial en celulares.
Frontend con SSR (TanStack Start) y backend REST independiente.
Despliegues y escalado independientes; hay que manejar CORS y el arranque en frío del plan gratuito.
El plan gratuito duerme la API y el primer ingreso del domingo tardaba medio minuto.
Ping periódico externo más un workflow de GitHub Actions que despierta la API antes del culto.
Costo cero y experiencia fluida. Dependencia de un servicio gratuito, documentada.
Los audios pesan y no deben ser públicos.
Cloudflare R2 (API S3) y URLs firmadas temporales emitidas por el backend.
Sin costo de egreso y acceso controlado por permisos; el cliente nunca ve las credenciales.
Cada músico necesita su tono y el PDF debe respetar el formato.
Letra con acordes entre corchetes; un parser puro transpone, alinea y renderiza (pantalla y PDF).
Edición simple y tests unitarios del parser; los casos borde (acordes con bajo, líneas largas) se cubren con pruebas.
Se pidió sugerir listas variadas sin repetir lo reciente.
Algoritmo determinista con pesos por rotación, reglas de temas y canciones enganchadas.
Resultados explicables, gratuitos y testeables.
Producción la usa gente real cada semana.
Flujo develop → PR → main con tipos, lint, tests y build como checks requeridos.
Menos regresiones; el costo es un ciclo de revisión más largo, aceptable para el riesgo.
Elegidas por productividad, tipado de punta a punta y costo operativo cero.
Capturas reales con datos de demostración inventados. Tocá una imagen para ampliarla.

Portada con partículas y accesos rápidos. Destaca la lista en la que el músico está asignado.
lista-propia:ver
Repertorio con búsqueda, filtro por tipo y etiquetas, vista tarjetas o lista y favoritos.
cancion:ver
Combinación de tipo, tema y tono para encontrar la canción justa en segundos.
cancion:ver
Letra con acordes alineados, transposición de tono y tamaño de letra, con descarga a PDF.
cancion:ver
Reduce la canción a su progresión y repeticiones, pensado para tocar leyendo de un vistazo.
cancion:ver
Cambia de tono toda la canción conservando la forma de los acordes con bajo.
cancion:ver
Lectura limpia para cantar, con botón de reproducir y salto directo a la canción elegida.
cancion:ver
Audio propio o YouTube, cola, repetir tramo y controles con efecto glass.
escuchar:ver
Listas por fecha con estado, equipo asignado y duración total (sin sumar la ofrenda).
lista:ver
Secciones, tono por canción, equipo por categorías y copia directa a WhatsApp.
lista:ver
Asistente con fecha, título automático, generación aleatoria y plantillas predefinidas.
lista:crear
Reordenamiento y asignación de sección de cada canción, con duración recalculada al instante.
lista:editar
Músicos con sus instrumentos; solo se ofrecen para asignar quienes pueden tocarlos.
usuario:ver
Edición visual de roles y permisos por recurso y acción. Cambios efectivos al instante.
rol:editar
Canciones más tocadas, rotación y uso por mes.
estadistica:ver
Visualización con Recharts y búsqueda de una canción para traer las listas donde se tocó.
estadistica:ver
Atajo personal a las canciones que más se usan.
favorito:crear
Guía paso a paso para Android e iPhone: la PWA se agrega a la pantalla de inicio.
PWA
Acceso con cuenta o como invitado de solo lectura.
authProbado en anchos de 320 a 430 px con un script automatizado que mide desbordes.






Los que más enseñaron. Filtrá por área.
La API gratuita se dormía y el primer ingreso del domingo tardaba cerca de 30 s.
Ping externo periódico más un workflow programado que la despierta antes del culto.
En iPhone, al enfocar un campo Safari hacía zoom y la pantalla quedaba desplazada.
Inputs a 16 px en dispositivos táctiles y un detector automatizado de desbordes a 320–430 px.
Un acorde con bajo como A/C# se partía al saltar de línea y se leía mal.
El parser trata el acorde como una unidad indivisible y ajusta el ancho al envolver; cubierto con tests.
Un texto entre corchetes en la letra se interpretaba como acorde y rompía la alineación.
Validación del token contra la gramática de acordes: lo que no lo es se conserva como texto.
La duración de la lista sumaba la ofrenda y no coincidía con lo que el equipo tocaba.
Regla de negocio explícita: se usa la primera pista subida, si no hay, la duración del video; la ofrenda no suma.
El reproductor fijo tapaba las anotaciones y el contenido en tablet.
Reserva de espacio inferior dinámica y barra lateral que se pliega en tablet.
Cambiar la fecha de una lista dejaba un título desactualizado.
Título derivado de la fecha mientras no haya sido editado a mano.
Los roles tenían permisos fijos y cada ajuste requería desplegar.
RBAC por permisos en base de datos y pantalla de edición de roles.
Un lint fallaba en CI solo por saltos de línea de Windows.
Regla de fin de línea unificada y verificación local previa al PR.
Los videos de YouTube mostraban bordes negros según el formato.
Portada con mejor resolución y recorte adaptado a la relación de aspecto del video.
Autenticación, canciones, listas y primer reproductor. Modelo relacional y migraciones.
RBAC granular editable, acceso de invitado y vistas según rol.
Acordes con transposición, solo‑acordes, PDF, repetir tramo y letra a tamaño ajustable.
Secciones, generador de listas, equipo por instrumento, notas y copia a WhatsApp.
Revisión de tamaños de celular, estilo glass y dorado, CI obligatorio y bitácora de cada cambio.
Diseñado, desarrollado, desplegado y mantenido de punta a punta.