Repository navigation
MS7
This is just a reference to guide the construction of the backlog in each repository's list of issues.
[BE] Backend
[FE] Frontend
[AN] Analytics
| Feature | Description | Acceptance criteria | Repository |
|---|---|---|---|
| [BE] Core & Auth | Set up NestJS/Prisma, DB and migrations, JWT+Argon2 authentication and user profile. | App and Docker start register/login/refresh return tokens; GET/PATCH/DELETE /usuarios/me with cascade delete. | backend |
| [BE] Well-being | Daily check-in, panic button, Respira, Support and Protocols. | One check-in/day; contacts + panic events with response time; breathing sessions; emergency lines; protocols with steps. | backend |
| [BE] Content & Activity | Flashcards, Games, Audios and unified Activity tab. | Public catalogs; sessions/views require auth; paginated GET /actividad feed for the user. | backend |
| [BE] Analytics & Wrap-up | Telemetry, institutions/analytics, privacy, Swagger and deploy. | Events → 202; summary with k-anonymity ≥5; 403 without consent; Swagger at /api/docs; Docker OK. | backend |
| [FE] Breathing exercises | Breathing exercises screen with guided animation and sessions. | The user sees breathing exercises; selecting one opens an animated guide that expands and contracts in sync with the inhalation, retention, and exhalation phases, featuring optional haptic feedback; a timer indicates the remaining time; the user can pause or end the exercise, and a confirmation message appears upon completion. | Flutter and Kotlin |
| [FE] Daily Check-in | Daily user mood check-in via an interactive survey. | User picks a mood from a set of icons and can add an optional note; only one check-in is allowed per day (UI blocks a second and shows a message); current and longest streak are displayed; past check-ins shown in a calendar. | Flutter and Kotlin |
| [FE] Flashcards | Category-based cards with swipe navigation. | The user views cards by category, selects the ones they want to see, and swipes left or right to navigate between them; each card displays its title and content, featuring smooth transitions and a clear indication when the deck is finished. | Flutter and Kotlin |
| [FE] Registration, Login, and Profile | Account creation, sign-in and profile management. | Users can register and log in using validated forms with clear error messages; the session persists after restarting the application; the profile screen allows viewing and editing of the name, photo, and language; and users can log out and delete their account after confirmation. | Flutter and Kotlin |
| [FE] Panic Button | Panic button with quick contact to your support network via call or message. | The user can add, edit, and delete the emergency contact; selecting this contact offers the option to call and/or send a message and displays the connection or confirmation status, while an appropriate message is shown if there is no connection. | Flutter and Kotlin |
| [FE] Support network | Support network screen with emergency lines and contacts. | The user views a list of emergency lines—including names, phone numbers, and descriptions—and can filter by personal contacts or emergency lines; tapping a line initiates a call; personal assistance contacts are displayed alongside them; and loading and no-data states are managed. | Flutter and Kotlin |
Flutter's Product Backlog
Kotlin's Product Backlog
Backend's Product Backlog
flowchart TB
subgraph CLIENTES["Clientes móviles"]
subgraph KOTLIN["App Android - Kotlin (MVVM)"]
K_VIEW["View<br/>Pantallas"]
K_VM["ViewModel<br/>Estado de pantalla"]
K_REPO["Repository<br/>Cliente HTTP"]
K_LOCAL[("Almacenamiento local<br/>Datos sin consentimiento<br/>y audios propios")]
K_VIEW --> K_VM
K_VM --> K_REPO
K_REPO --> K_LOCAL
end
subgraph FLUTTER["App Flutter (MVVM)"]
F_VIEW["View<br/>Pantallas"]
F_VM["ViewModel<br/>Estado de pantalla"]
F_REPO["Repository<br/>Cliente HTTP"]
F_LOCAL[("Almacenamiento local<br/>Datos sin consentimiento<br/>y audios propios")]
F_VIEW --> F_VM
F_VM --> F_REPO
F_REPO --> F_LOCAL
end
end
DIALER["Servicio de llamadas<br/>del dispositivo"]
K_VM -->|"llama a contacto<br/>o línea de emergencia"| DIALER
F_VM -->|"llama a contacto<br/>o línea de emergencia"| DIALER
subgraph BACKEND["Backend - NestJS + TypeScript (Docker)"]
API["API REST versionada<br/>Documentación Swagger"]
subgraph MODULOS["Módulos funcionales"]
M_USR["Usuarios, perfil<br/>y rachas"]
M_BIEN["Check-in, Respira, Protocolos,<br/>Flashcards, Juegos y Audios"]
M_APOYO["Botón de pánico, contactos<br/>y líneas de emergencia"]
M_ACT["Actividad<br/>del usuario"]
M_ANA["Analítica institucional<br/>y telemetría"]
end
PRISMA["Prisma ORM<br/>Migraciones y seed"]
API --> M_USR
API --> M_BIEN
API --> M_APOYO
API --> M_ACT
API --> M_ANA
M_USR --> PRISMA
M_BIEN --> PRISMA
M_APOYO --> PRISMA
M_ACT --> PRISMA
M_ANA --> PRISMA
end
subgraph PERSISTENCIA["Persistencia"]
DB[("PostgreSQL<br/>Tablas de la aplicación")]
VISTAS["Vistas de analítica<br/>vista_actividad_usuario<br/>resumen_actividad_departamento"]
DB -.->|"alimenta"| VISTAS
end
K_REPO -->|"HTTPS / JSON"| API
F_REPO -->|"HTTPS / JSON"| API
PRISMA -->|"SQL"| DB
M_ANA -.->|"lee agregados"| VISTAS
M_ACT -.->|"lee"| VISTAS

We chose NestJS due to the way it organizes everything into modules, which fits perfectly onto the five internal modules of the backend: Users, Well-being, Support/Panic, Activity, Analytics. Each member can work on their own module without affecting others. We also chose Prisma due to its typed autocomplete and easier migrations. PostgreSQL was chosen because the model is relational and because it let us gather analytics using database views.
We chose JWT because we wanted clients to keep functioning offline without depending on a "live" session.
The ViewModel calling the phone's calling service directly was chosen to avoid depending on internet working to call a contact during a crisis.
When a user doesn't want their data saved, that data just stays on the phone and never reaches the backend..
In the class diagram, User composes Check-in, Panic, SupportContact, and Activity log. We decided this because deleting the account wipes everything tied to that person instead of leaving orphaned data floating around.
Finally, we used MVVM with a Repository as the only thing that talks to the API, because this let us test the ViewModels without needing a real connection, and gave us a single place to decide whether a piece of data gets sent to the backend or just stays stored locally.
The example structure for the mood_checkin feature is implemented using MVVM in Flutter, as follows:
lib/
├── main.dart
├── home/home_screen.dart
└── features/
├── mood_checkin/
│ ├── model/ mood_state.dart, mood_checkin.dart
│ ├── data/ mood_repository.dart (contrato), fake_mood_repository.dart
│ ├── viewmodel/ mood_checkin_viewmodel.dart
│ └── view/ mood_checkin_screen.dart
test/
└── mood_checkin_viewmodel_test.dart
The example structure for the mood_checkin feature was implemented using MVVM in Kotlin (Android), as follows:
app/src/
├── main/java/com/zenmind/
│ ├── MainActivity.kt
│ ├── home/HomeScreen.kt
│ └── features/
│ └── moodcheckin/
│ ├── model/ MoodState.kt, MoodCheckin.kt
│ ├── data/ MoodRepository.kt (contrato), FakeMoodRepository.kt
│ ├── viewmodel/ MoodCheckinViewModel.kt
│ └── view/ MoodCheckinScreen.kt
└── test/java/com/zenmind/
└── MoodCheckinViewModelTest.kt
-
How do the smart features help to generate value? The Daily Check-in creates the habit because it makes progress visible through a streak and a calendar with past check-ins, incentivizing users to maintain regularity in the process of bettering their well-being. Also, both Flashcards and the Activity feed configure according to what the student has looked at before, to feel unique and personalized to each individual. Finally, Analytics turns raw usage data into anonymized summaries that the Decanatura can use, like noticing which weeks are more stressful for which majors, without ever seeing one specific student's data.
-
How do the CAS features help to generate value? The panic button and support network go directly to the phone's call/message function instead of passing through the backend, to ensure that students in a crisis can contact someone regardless of internet. Also, breathing exercises use vibrations (haptic feedback) synchronized to the breathing phases to keep the student's focus without having them look at the screen.