11 KiB
CLAUDE.md — Guía de desarrollo de Rachita
Este archivo orienta a cualquier agente de IA (Claude, Copilot, etc.) o desarrollador humano que trabaje en este repositorio. Contiene las decisiones de arquitectura ya tomadas, las convenciones a seguir y el estado/plan del proyecto. Léelo antes de escribir código.
El producto y sus requisitos completos están en PRD-Rachita.md. Este documento (
CLAUDE.md) es el complemento técnico: cómo se construye, no qué se construye.
1. Resumen del proyecto
Rachita es una app de hábitos y creatividad para tablet Android, dirigida a niñas/niños de 6–10 años. Mascota virtual + hábitos diarios + rachas + museo de dibujos + sistema de monitoreo de batería (la mascota "se cansa" con poca batería y "duerme" mientras la tablet carga, bloqueando el uso).
Prototipo de referencia visual/UX: Rachita.html (bundle React exportado, no es el código fuente final — úsalo solo como referencia de diseño, animaciones, copy y flujos, ver §9).
2. Decisiones de arquitectura (confirmadas)
| Decisión | Valor |
|---|---|
| Plataforma cliente | Android nativo (Kotlin) — sin iOS en v1 |
| UI Android | Jetpack Compose |
| Build system Android | Gradle con Kotlin DSL (build.gradle.kts) |
| SDK mínimo Android | API 26 (Android 8.0) — minSdk = 26 |
| Package name | mx.paputec.rachita |
| Backend | ASP.NET Core Web API, .NET 10 |
| Arquitectura backend | REST clásico versionado (/api/v1/...) con capas Controller → Service → Repository |
| ORM | Entity Framework Core (Code First + Migrations) |
| Base de datos | PostgreSQL |
| Autenticación | Sin login para la niña. Perfil local vinculado a un código de familia (family code) para emparejar Rachas en equipo. Gate parental simple (no es "auth" real) para pantallas sensibles (Ajustes, invitaciones) |
| Persistencia local Android | v1: la app funciona con almacenamiento local simple (DataStore/Room mínimo) para hábitos/museo offline-first; sincronización real con backend se agrega cuando se implemente "Rachas en equipo". Room completo con sync es deseable, no bloqueante |
| Hosting backend | Servidor Ubuntu propio, vía Docker (contenedor de la API) + Nginx como reverse proxy + systemd para gestionar el stack |
| Repositorio | Monorepo único: git.paputec.mx/johannvelazquez/h-bitosInfantiles con carpetas /app (Android) y /backend (.NET) |
| CI/CD | No configurado todavía. Se agrega más adelante (posible runner de build dedicado, ver skill migrate-ci-build-runner si aplica) |
| Testing | Sí, desde el inicio: JUnit/Compose UI tests en Android, xUnit en .NET |
| Assets de la mascota | Se mantiene el enfoque ilustrativo por código (formas vectoriales/Compose Canvas), igual que el prototipo HTML — no hay assets de diseño gráfico todavía |
2.1 Alcance del primer sprint (MVP real, no todo el PRD)
Construir solo estos 3 módulos primero, de punta a punta (UI + lógica + persistencia local, sin backend aún):
- Onboarding / Selección de compañero (Avatar)
- Dashboard principal de hábitos y rachas
- Sistema de Monitoreo de Batería (overlay batería baja + pantalla de bloqueo en carga)
Los demás módulos del PRD (Museo, Galería, Rachas en equipo, Alertas/notificaciones, Widgets) se abordan en sprints posteriores, en ese orden de prioridad salvo indicación contraria.
3. Estructura del repositorio (monorepo)
h-bitosInfantiles/
├── CLAUDE.md ← este archivo
├── PRD-Rachita.md ← requisitos de producto completos
├── Rachita.html ← prototipo visual (referencia, no se ejecuta en prod)
├── README.md
├── app/ ← proyecto Android (Kotlin + Jetpack Compose)
│ ├── build.gradle.kts
│ ├── settings.gradle.kts
│ └── app/
│ └── src/main/java/mx/paputec/rachita/
│ ├── ui/ ← pantallas Compose por feature
│ ├── data/ ← repos locales, DataStore/Room, modelos
│ ├── domain/ ← casos de uso / lógica de negocio
│ └── di/ ← inyección de dependencias (Hilt)
└── backend/ ← proyecto .NET 10 Web API
├── Rachita.sln
├── src/
│ ├── Rachita.Api/ ← Controllers, Program.cs, DI, middlewares
│ ├── Rachita.Application/ ← Services, DTOs, interfaces
│ ├── Rachita.Domain/ ← Entidades, reglas de negocio puras
│ └── Rachita.Infrastructure/ ← EF Core, DbContext, Repositories, Migrations
└── tests/
└── Rachita.Api.Tests/
Regla: el código Android nunca depende directamente de EF Core ni del backend; se comunica solo vía API REST (DTOs propios en el cliente).
4. Convenciones de código
4.1 Android / Kotlin
- Arquitectura por feature dentro de
ui/(ej.ui/onboarding,ui/dashboard,ui/battery), no por tipo de archivo. - Patrón MVVM:
Screen.kt(Composable) +ViewModel.kt(StateFlowde UI state) +UiStatedata class. - Inyección de dependencias con Hilt.
- Nombres:
PascalCasepara Composables y clases,camelCasepara funciones/variables,UPPER_SNAKE_CASEpara constantes. - Un Composable por archivo cuando sea una pantalla completa; sub-componentes pequeños pueden compartir archivo si son privados (
private fun). - Preview de Compose (
@Preview) obligatorio en componentes visuales reutilizables. - Colores, tipografías y espaciados centralizados en
ui/theme/(Color.kt,Type.kt,Shape.kt) siguiendo la guía de estilo del PRD (§6). - Animaciones con
animateFloatAsState,rememberInfiniteTransition, etc. — replicar timings del prototipo (ver PRD §6.4).
4.2 Backend / .NET
- Separación estricta de capas:
Api(controllers, DTOs de request/response) →Application(servicios, interfacesIXxxService) →Domain(entidades y reglas puras, sin dependencias externas) →Infrastructure(EF Core,DbContext, implementaciones de repositorios). - Controllers delgados: solo reciben request, llaman al service, devuelven response. Nada de lógica de negocio en el controller.
- Repositorios detrás de interfaces (
IHabitRepository, etc.) definidas enApplicationoDomain, implementadas enInfrastructure. - DTOs distintos de las entidades de dominio (nunca exponer entidades EF directamente en la API).
- Migraciones EF Core versionadas y con nombre descriptivo (
dotnet ef migrations add AddTeamStreaks). - Endpoints versionados:
/api/v1/.... - Convención REST: sustantivos en plural, verbos HTTP correctos (
GET /api/v1/habits,POST /api/v1/habits/{id}/complete).
4.3 General
- Idioma del código (nombres de variables, clases): inglés. Idioma de la UI/copy visible al usuario: español (MX), tal como en el PRD y el prototipo.
- Commits: mensajes claros en español o inglés consistente por PR, formato libre (Conventional Commits deseable pero no obligatorio).
- No se necesita documentar cada cambio en archivos markdown nuevos salvo que se pida explícitamente.
5. Modelo de datos de referencia
Basado en PRD §9, adaptado a EF Core (backend) y su equivalente local (Android):
Profile (childName, avatarKind, customAvatarUri, level, xp, streak, familyCode)
Habit (id, name, subtitle, icon, color, active, createdAt)
HabitLog (habitId, date, done) -- 1 registro por hábito por día
Artwork (id, date, imageUri, title, note, medium)
TeamStreak (id, ownerProfileId, partnerProfileId, sharedHabitId, streak, week[7])
TeamStreakDay (teamStreakId, date, myDone, theirDone, nudgedByMe, nudgedByThem)
Settings (profileId, notifyLowBattery, notifyWhileCharging, habitReminderAt, confettiOn)
Reglas clave a implementar (ver PRD §5.2 y §5.7):
- La racha global sube +1 solo si todos los hábitos activos del día quedaron
done = trueantes de medianoche. - En
TeamStreak, la racha crece solo simyDone && theirDoneel mismo día calendario.
6. Sistema de Monitoreo de Batería — notas técnicas
- Usar
BatteryManager/Intent.ACTION_BATTERY_CHANGED(oregisterReceiverconIntentFilter(Intent.ACTION_BATTERY_CHANGED)) para leer nivel y estado de carga en tiempo real — no hacer polling manual. - Umbral batería baja:
< 20%→ mostrar overlay (Composable conDialogo superposición a pantalla completa), no bloqueante, con opción "Ahora no". - Detección de carga:
BatteryManager.EXTRA_STATUS == BATTERY_STATUS_CHARGING(oplugged != 0) → activar pantalla de bloqueo total (Activity/Composable a pantalla completa, sin back button funcional, ver PRD CA-01). - El botón "Ya la desconecté" debe verificar el estado real del sistema antes de desbloquear (no confiar ciegamente en el tap del usuario) — mitigación de riesgo listada en PRD §13.
- Evaluar
Screen Pinning(modo kiosco, PRD D-24) cuando se implemente el bloqueo, para impedir salir de la app durante la carga.
7. Cómo ejecutar el proyecto (a completar conforme se construya)
Android
cd app
./gradlew assembleDebug
Pendiente: confirmar si se usará emulador Android Studio o tablet física para pruebas (no definido aún).
Backend
cd backend
dotnet restore
dotnet ef database update --project src/Rachita.Infrastructure --startup-project src/Rachita.Api
dotnet run --project src/Rachita.Api
Docker (backend, producción)
docker build -t rachita-api ./backend
docker run -d -p 5000:8080 --env-file .env rachita-api
Pendiente definir: variables de entorno exactas, configuración de Nginx (dominio/subdominio), certificados TLS y compose file cuando se llegue al sprint de despliegue.
8. Pendientes / decisiones abiertas
Estas preguntas del PRD (§16) siguen sin resolver y pueden afectar el modelo de datos o la UX; confirmarlas antes de implementar el módulo correspondiente:
- ¿La racha global se pierde por completo al fallar un día, o hay "congelador" desde v1?
- ¿Los hábitos tienen horario límite individual?
- ¿Quién etiqueta el "medio" del dibujo (crayón/acuarela/…)?
- ¿Reporte/panel para el adulto en v1 o se pospone?
- Dominio/subdominio exacto y configuración de Nginx para el backend en el servidor Ubuntu (pendiente de confirmar con el usuario).
- Estrategia exacta de sincronización offline↔backend para hábitos y museo (más allá de "Rachas en equipo") aún no definida.
9. Uso del prototipo Rachita.html
Es un bundle exportado de una herramienta de diseño (contiene un manifiesto base64 + template comprimido), no es código fuente Kotlin/React reutilizable directamente. Úsalo solo para:
- Extraer valores exactos de la guía de estilo (colores, radios, sombras, timings de animación).
- Confirmar el copy exacto en español de cada pantalla.
- Revisar el flujo de estados (
showDash,isLow,isCharging, etc.) como referencia de máquina de estados al implementar el ViewModel de Compose.
Si necesitas inspeccionar su contenido interno, ya fue desempaquetado una vez en _extracted/ (carpeta temporal, no versionar en git — agregar a .gitignore si se conserva).