LUCIANO CARRIZO
mobile-calendar
Todos los proyectos
Archivado

mobile-calendar

App mobile (Expo + React Native + TypeScript) para organizar la cursada: materias con horario y nota, trabajos con estado y notas sueltas, en vistas Hoy, Día, Semana y Calendario. Fue mi primera app pensada solo para mobile, hecha en 8 días con arquitectura DDD y datos en memoria — y la que sembró la idea que después maduré en my-school-app.

TypeScriptReactExpo
Por qué esta app

Mi primera app pensada solo para mobile

mobile-calendar es una app de horarios académicos: gestiona materias (Cursada, con su horario y su ubicación), trabajos y entregas con estado, y notas sueltas, y las muestra en cuatro vistas — Hoy, Día, Semana y Calendario. El problema que quería resolver era el mío: tener las cursadas y las entregas en un mismo lugar, en el teléfono, sin depender de una app ajena.

Pero el motivo real por el que este proyecto existe es otro, y es el que importa para leer todo lo que sigue: fue la primera app que encaré exclusivamente para mobile, y en solitario. No un ejercicio de curso ni un tutorial seguido paso a paso: un proyecto propio de punta a punta, en 8 días de trabajo — el primer commit es del 28 de marzo de 2026, el último del 4 de abril.

Ocho días es poco, y se nota en varias partes del repo. Lo cuento igual, porque la parte interesante de este caso no es el producto terminado: es lo que aprendí acá y adónde fue a parar.

Cómo la pensé

DDD sobre un dominio que hablaba mi idioma

Podía haber armado esto con un par de pantallas y un useState grande. Elegí lo contrario: arquitectura por capas, con Domain-Driven Design.

El dominio quedó en español, porque los conceptos son de la facultad y traducirlos solo agregaba ruido: Cursada, Trabajo, Nota, Horario, Persona, Ubicacion. Lo técnico —carpetas, interfaces, tests— en inglés. Las entidades son clases, no objetos planos, y varias tienen Value Objects propios que se validan en el constructor: Email, Telefono, Descripcion, Calificacion. La idea era simple: si un objeto existe, es porque es válido. No hay una Calificacion en un estado imposible esperando que alguien la revise más adelante.

El caso de Telefono es el que mejor muestra la intención: no valida con una expresión regular inventada, usa libphonenumber-js para validar números argentinos de verdad. La regla de negocio vive en el objeto del dominio, no repartida en las pantallas que lo usan.

Arriba de eso, las capas: domain/ con entidades, errores e interfaces de repositorio (ICursadaRepository, ITrabajoRepository, INotaRepository); application/ con los casos de uso (CursadaUseCases, TrabajoUseCases, NotaUseCases); data/ con las implementaciones concretas de esos repositorios; y presentation/ con pantallas, componentes, navegación —React Navigation v6, Stack más Bottom Tabs— y un theme.ts con los tokens de color.

Lo que sí probé fue justamente esa parte: hay 16 archivos de test con Vitest, y no están donde suelen estar los tests de adorno. Diez cubren entidades y value objects, tres los repositorios y tres los casos de uso. Cero tests de UI. Fue una decisión consciente sobre dónde valía la pena gastar el esfuerzo en un proyecto de 8 días: la validación del dominio es lo que rompe en silencio, mientras una pantalla mal alineada se ve a simple vista.

Los bocetos

Así arrancó el diseño: marcador y pizarra

Antes de escribir la primera pantalla dibujé las vistas a mano. Están commiteadas en el repo, en resources/images/, y son exactamente eso: fotos de bocetos hechos con marcador sobre una pizarra. No son capturas de la app corriendo.

Boceto a mano en pizarra de la pantalla Cursadas: dos materias (Física, Sociales) en tarjetas, cada una con días de cursada, cantidad de trabajos, nota y conteo de entregas; botón + arriba a la derecha y tres tabs abajo
La pantalla Cursadas dibujada a mano: cada materia como una tarjeta con sus días, su nota y el estado de sus entregas.

El boceto de Cursadas es el que más decidido está: cada materia es una tarjeta con sus días de cursada arriba y, debajo, los contadores que resumen cómo va —trabajos, nota, entregas.

Boceto a mano en pizarra de la vista Hoy: columna de horas de 13 a 18 a la izquierda y bloques de materias (Matemática, Física, Sociales) ocupando sus franjas, con el día y la fecha en el encabezado
La vista Hoy: una agenda por hora con las materias del día ocupando su franja.
Boceto a mano en pizarra de la vista Semana: grilla con las horas en la primera columna y los siete días de lunes a domingo como columnas, con materias abreviadas (MAT, FIS, SOC) ubicadas en sus celdas
La vista Semana, en horizontal: grilla de días por horas, con las materias abreviadas en su celda.

Los tres dibujos comparten una decisión que después fue la del código: la barra de tabs abajo, fija, como única forma de moverse entre vistas. Y la semana está dibujada en horizontal, con la pizarra girada, mientras Hoy y Cursadas están en vertical: la grilla de siete días por hora pedía otra orientación, y eso quedó resuelto en el papel y no discutiéndolo con el emulador.

Los dejo acá tal cual son, con la mano y el brillo del marcador incluidos, porque muestran el paso que normalmente no se ve: la app no arrancó en un editor de código.

Lo que quedó sin pulir

Tres cosas que hoy haría distinto

Hay tres agujeros en este repo, y ninguno es un detalle.

La persistencia no existe. La capa de datos es en memoria: cerrás la app y perdés todo. El README lo declara como mejora futura —“Future enhancement: Integrate AsyncStorage or SQLite for persistence”— pero futura se quedó. Toda la arquitectura de repositorios estaba armada justamente para que enchufar un storage real fuera cambiar una implementación detrás de una interfaz, y aun así no llegué a hacerlo. Tener el lugar preparado no es lo mismo que resolverlo.

El historial no cuenta nada. Son 4 commits en total, y el grueso de la app entera —dominio, capas, pantallas, navegación— entró en uno solo: feat: complete academic calendar app with DDD architecture. No hay forma de leer en ese repo en qué orden se construyó nada, ni de volver a un punto intermedio.

No hay CI. Los 16 tests de Vitest existen, pero nada los corre solo: no hay .github/workflows/. Que pasen dependía de que yo me acordara de correrlos.

Ninguna de las tres es una excusa de tiempo. Son las cosas que en la primera vuelta uno todavía no sabe que va a extrañar.

De acá salió my-school-app

El primer paso de un recorrido que sigue en otro proyecto

Este proyecto está archivado y no lo escondo. Pero archivado no es lo mismo que descartado: mobile-calendar es el origen directo de my-school-app, y esa es la razón por la que está en el portafolio.

La cronología lo dice sin que yo tenga que adornarla: mobile-calendar cierra su último commit el 4 de abril de 2026, y 18 días después, el 22 de abril, arranca my-school-app. Mismo problema —organizar la cursada, las materias, las entregas, el calendario— y el mismo stack de base: Expo, React Native, TypeScript.

Lo que cambió es todo lo que acá había quedado a medias. my-school-app tiene persistencia real, cross-platform, en lugar de datos que se van al cerrar la app. Usa Expo Router y Zustand en vez de React Navigation clásico y contexto. Tiene i18n. Y su historial son 32 commits desglosados en fases numeradas, no un commit gigante: exactamente la carencia del punto anterior, corregida. Incluso el proceso de diseño maduró en la misma dirección: los bocetos a mano de la pizarra se convirtieron en 26 wireframes HTML commiteados antes de programar.

Es la misma idea, dos vueltas. La primera me sirvió durante un tiempo como calendario y libreta de notas, y sobre todo me enseñó qué era lo que le faltaba. Sin esta app —sin haberla usado y sin haberme chocado con sus tres agujeros— la segunda no habría empezado por donde empezó.

Siguiente paso

El caso muestra el código. Hablemos de lo que sigue.

mobile-calendar está documentado end-to-end: arquitectura, decisiones y lo que quedó pendiente. Si tenés preguntas sobre el enfoque, escribime.

Hablemos

o directamente → LuchoC.dev@gmail.com