Tabla de contenido
Una vez más aquí. Hoy vengo a dejar un pequeño artículo relacionado con una conversación que mantuve hace unos días. El caso es que estuve hablando con Fernando, que me contó que trabaja en una escuela de música, y que en ella tienen una base de datos que no dejan de ser hojas de excel, en la que guardan los alumnos. El hombre me comentaba que estaba pensando en hacer una interfaz web para poder dejar de trabajar con hojas de excel y tener algo que les permita a todos acceder a la base de datos desde cualquier sitio. Y como estos días estuve viendo una magnífica serie llamada Separados, se me ocurrió crear algo que pudiese serle de utilidad, pero que tuviese un toque de esta serie que estoy viendo, mezclado con algunos toques más de Cyberpunk. Pues bueno, así es como nació MDR – MacroData Rhythm.
La cosa es que por lo que Fernando me comentaba, en este caso en particular, gestionar el alumnado de esa escuela de música lo suelen hacer entre hojas de cálculo, agendas de papel y carpetas desordenadas. MDR — MacroData Rhythm nace como respuesta a ese problema cotidiano: un fichero digital estilo Rolodex que combina la nostalgia del archivador físico con una interfaz cassette-punk moderna, sin necesidad de servidor ni base de datos en la nube. Basta con tener los equipos o dispositivos conectados en la misma red y que se vean entre ellos.
¿Qué es MDR?
El proyecto es una aplicación web open source escrita en HTML, CSS y JavaScript vanilla. Todo el trabajo ocurre en el navegador: los datos se guardan en una base SQLite embebida (sql.js) y se persisten en IndexedDB. Eso significa que puedes abrir MDR en un equipo, importar un Excel o un CSV, editar fichas y exportar un archivo .db listo para llevar a otro ordenador, si es lo que necesitas. El código está publicado en GitHub bajo licencia GPL-3.0.
Si buscas una herramienta ligera de gestión de alumnos de música, un Rolodex digital educativo o un ejemplo real de SQLite en el navegador con interfaz cuidada, en las siguientes líneas de este artículo veremos qué es MDR, cómo se usa y qué partes del código merecen atención.
MDR (MacroData Rhythm) es un fichero de contactos y datos escolares orientado a conservatorios, academias y escuelas de música. Cada alumno se representa como una ficha de papel digital con campos como nombre, instrumento, curso, dirección, teléfono, email y notas. Además, cada ficha admite campos personalizados (por ejemplo, tutor o beca) que solo afectan a ese registro.
La experiencia visual no es un panel administrativo genérico. La metáfora principal es el Rolodex clásico: una rueda 3D de tarjetas que giras con el ratón, las flechas del teclado o arrastrando arriba y abajo. Al abrir una ficha, no aparece un modal plano de formulario web: la tarjeta aparece con líneas de papel, tipografía de máquina de escribir y una muesca metálica como las del archivo físico. Existe también una vista de clasificador por cursos, pensada para reorganizar alumnos entre niveles con arrastrar y soltar.
El público objetivo incluye docentes, secretarías de centros musicales, estudiantes de desarrollo web que quieran estudiar un proyecto front-end completo, y cualquiera que necesite una agenda offline-first sin depender de cuentas cloud. A decir verdad, esto no creo que pueda generar un expediente completo … tampoco es la idea con la que nació el proyecto.
Características generales de MDR

La rueda 3D es el corazón de la navegación. Solo la ficha central responde al clic o a Enter. Los correos de las tarjetas superior e inferior no son clicables, para evitar errores al girar. El sonido de giro imita el roce de cartulina y plástico, y puede silenciarse. Desde el escenario también puedes ordenar la rueda de A a Z o de Z a A.
La vista clasificador agrupa las fichas en cajones por curso. Cada tarjeta es compacta (nombre, instrumento y teléfono), muestra un indicador de agarre y se puede arrastrar a otro cajón. Al soltar, el curso del alumno se actualiza y se guarda en la base local. Cada grupo tiene su propio orden alfabético.

La ficha abierta permite leer, editar, imprimir y eliminar. En modo edición aparecen cajetines tipográficos, un badge “Modo edición”, un desplegable de curso (1º a 4º Grado más los cursos ya existentes) y la posibilidad de añadir o quitar campos personalizados solo en esa ficha. Se puede imprimir cada una de las fichas.
La importación acepta SQLite (.db), Excel (.xlsx / .xls) y CSV. Si ya hay datos y eliges añadir, MDR detecta nombres duplicados y pregunta si sobrescribir, omitir o crear una ficha nueva con otro nombre. La exportación genera un .db portable. Todo queda en el navegador gracias a sql.js e IndexedDB.
La estructura del repositorio es deliberadamente plana y fácil de leer:
- El archivo index.html monta la interfaz: splash de arranque, escritorio con rueda y clasificador, menú lateral de búsqueda e importación, y los overlays de mapeo de columnas, resolución de duplicados y ficha abierta.
- La hoja css/rolodex.css concentra el diseño visual: variables de color, tipografías Special Elite, Barlow Condensed y Source Serif 4, estilos 3D de la rueda, cajones del clasificador y la ficha en zoom.
- El archivo js/app.js orquesta la aplicación. La lógica vive en dos módulos JavaScript encapsulados en IIFE para no contaminar el ámbito global más de lo necesario. El archivo js/sqlite-store.js expone window.MdrStore, la capa de persistencia. SheetJS y sql.js se cargan desde CDN; el resto es código propio, sin frameworks.
Esta separación es una de las decisiones más importantes del proyecto: la interfaz no habla SQL directamente, y el almacén no conoce la rueda 3D. Eso facilita mantener, depurar y reutilizar la capa de datos.
app.js: la rueda 3D y el estado de la aplicación
En app.js, el estado central es un array de alumnos y un índice de giro continuo (indiceGiro). En lugar de saltar de forma brusca entre posiciones, el ángulo entre fichas adyacentes es fijo (ANGULO_FICHA = 34) y el radio de la rueda es constante (RADIO = 300). La función transformacionFicha calcula rotateX y translateZ para cada tarjeta visible. Solo se renderizan las fichas dentro de un rango cercano (RANGO_VISIBLE), lo que mantiene el rendimiento aunque la base crezca.
La navegación combina wheel, teclado y pointer events en el escenario. El arrastre vertical acumula desplazamiento y avanza o retrocede la rueda cuando se supera un umbral. Un detalle de UX clave: pointer-events está desactivado en las fichas no activas, y los enlaces mailto solo reciben clics en la ficha central. Así se evita que un email de la tarjeta superior “robe” el clic destinado a girar o abrir el centro.

La vista clasificador se construye en renderizarVistaTabla. Agrupa alumnos por curso, pinta cajones con cabecera tipo terminal y fichas compactas con grip. El HTML5 Drag and Drop marca el cajón destino (is-drop-target) y, al soltar, actualiza el campo curso del alumno y persiste. No hace falta un backend: el cambio es inmediato en memoria y en IndexedDB.
Ficha abierta, edición e importación en app.js

Abrir una ficha llama a abrirFicha y renderizarFicha. En lectura se genera una rejilla de dos columnas con tipografía de ficha. En edición, la tarjeta recibe la clase sheet-card–editing, el curso se rellena con un select dinámico (rellenarSelectCurso) y los campos extra se gestionan con filas creadas por crearFilaCampoExtra. Al guardar, leerCamposExtraDelFormulario valida nombres reservados y duplicados; luego se eliminan los extras antiguos solo de esa ficha y se aplican los nuevos. El resto de alumnos no se toca.
La importación es otro bloque relevante para quien estudie el código. Excel y CSV pasan por un mapeador de columnas con alias en español e inglés (ALIAS_CAMPOS). Tras confirmar el mapeo, pedirModoImportacion pregunta si reemplazar o añadir. Si se añade, resolverDuplicadosAlAnadir recorre conflictos de nombre uno a uno con un modal de sobrescribir, omitir o crear. Es un flujo asíncrono basado en promesas que mantiene la UI clara incluso con muchos duplicados.
sqlite-store.js: SQLite en WebAssembly e IndexedDB
El módulo sqlite-store.js es el otro pilar técnico. Usa sql.js para ejecutar SQLite compilado a WebAssembly dentro del navegador. Al iniciar, intenta recuperar bytes previos desde IndexedDB (base mdr-sqlite-v1). Si no hay datos, construye el esquema y carga una semilla (datos por defecto o migración desde un localStorage legado).
La API pública window.MdrStore permite iniciar, leer alumnos, reconstruir la base desde un array, persistir, exportar bytes e importar un .db externo. asegurarEsquema crea la tabla de alumnos y añade columnas faltantes cuando hace falta, de modo que los campos personalizados no rompan el esquema. persistir serializa la base en memoria y la guarda en IndexedDB; exportar descarga un archivo .db real que puedes volver a importar en MDR u otro cliente SQLite compatible.
Diseño, accesibilidad práctica y experiencia de uso
El CSS no es decoración secundaria: sostiene la metáfora del producto. La rueda usa transformaciones 3D y una carcasa de plástico. El clasificador usa cajones con borde cian e inset shadow; la ficha abierta anima un zoom (sheet-zoom-in) y un backdrop semitransparente para que la rueda siga visible. En impresión, reglas @media print ocultan la UI y la muesca inferior.
Hay detalles pensados para uso real: teléfono limitado a dígitos, búsqueda en el menú, atajos de teclado, favicon del logo, splash de arranque y un enlace al repositorio en el pie. No pretende ser un LMS completo: pretende ser un fichero digital de alumnos de música que se siente físico, rápido y portable.
Cómo probar MDR
Este pequeño proyecto lo puedes probar en la version online que he dejado en la página de ejemplos. También puedes clonar o descargar el repositorio. Incluye datos-ejemplo.csv y datos-ejemplo-importacion.db para probar importaciones en minutos.
MDR muestra interacción 3D, drag and drop, mapeo de importaciones, resolución de conflictos, impresión y una capa SQLite + IndexedDB bien encapsulada. Si trabajas en gestión de alumnos, en front-end vanilla o en aplicaciones offline-first, este Rolodex digital es un caso de estudio concreto, documentado y listo para extender.
MacroData Rhythm demuestra que una aplicación web sin frameworks puede ofrecer una experiencia interesante y una persistencia seria. Desde la rueda 3D hasta el clasificador por cursos y la edición tipográfica de fichas, el proyecto une estética y utilidad. Si buscas un fichero digital estilo Rolodex para escuela de música, o un ejemplo open source de SQLite en el navegador, visita el código en GitHub y pruébalo en local.
