App de fitness inteligente: Especificación de la arquitectura del cliente
ArtefactoEste es el artefacto que se usa en el episodio 3: Dale un cerebro a tu app y en el episodio 4: El plan de implementación de apps sin código. Puedes usar esta especificación como referencia para las vistas de frontend, los componentes de IU reutilizables, la administración de estados del cliente y los casos de prueba en lenguaje natural.
Accede para ver este artefacto
Accede con tu Perfil del desarrollador de Google para ver y copiar el artefacto completo que se usa en la serie Build It!
Se requiere un perfil de desarrollador
No cumples con los requisitos para tener un perfil del desarrollador. Notifica a tu administrador de Workspace para que habilite esta función.
Crear un Perfil del desarrollador
Crea un Perfil del desarrollador de Google gratuito para desbloquear todas las instrucciones y los artefactos de Build It!
Únete a Builder Central para desbloquear
Reclama tu insignia de miembro de Builder sin costo con un solo clic para desbloquear todas las instrucciones y los artefactos de Build It.
Estado: Listo para la sesión de planificación (redacción con el complemento de planificación del cliente)
Documento complementario: Especificación de la arquitectura de datos
Objetivo de la arquitectura: Reconstrucción limpia, mantenible, modular y comprobable del frontend del prototipo de fitness inteligente de AI Studio.
0. Pila técnica principal y estándares de ingeniería
- Framework de entorno de ejecución: Next.js (App Router, React 19) + almacenamiento en caché de recursos sin conexión de apps web progresivas (AWP).
- Arquitectura de diseño: Tailwind CSS v4 + Tailwind Variants (para el diseño de componentes deterministas) + Lucide React (íconos).
- División de estado del cliente:
- Zustand (sesión local): Administra el estado volátil de la sesión de entrenamiento (
useActiveSessionStore), los cronómetros, los búferes de series activas y la secuenciación de pasos calculada previamente. Se sincronizó conlocalStoragepara la recuperación del bloqueo del teléfono. - TanStack Query (estado del servidor): Administra el almacenamiento en caché de documentos de Firestore, la revalidación en segundo plano y las actualizaciones optimistas para
weekly_plans,user_profiles,prsyworkout_logs.
- Zustand (sesión local): Administra el estado volátil de la sesión de entrenamiento (
- Visualización de gráficos: Recharts (con diseño de tokens personalizados de modo oscuro de gimnasio).
- Autenticación: Firebase Authentication con el encabezado de autenticación de token del portador que se pasa a todos los extremos del servidor.
1. Principios de diseño y principios de frontend
- Ergonomía pensada para el gimnasio: Diseñado para un funcionamiento táctil con una sola mano durante el entrenamiento, incluso con las manos sudorosas. Objetivos táctiles amplios (mínimo de 48 × 48 dp), legibilidad de alto contraste y escritura mínima requerida.
- IU optimista y resiliencia sin conexión: El registro de series, el inicio de temporizadores de descanso y el cambio de ejercicios deben responder de forma instantánea (<16 ms) en la IU. La sincronización en segundo plano controla la persistencia del servidor en
POST /api/workouts/logsin bloquear al usuario. - Separación estricta de responsabilidades: Los componentes de presentación o tontos reciben datos y emiten eventos con propiedades; las vistas de contenedores inteligentes administran la lógica empresarial, los almacenes de estado y la coordinación de la API.
- UX de mutación en etapas: Las propuestas generadas por el coach potenciado por IA (
POST /api/coach/chat) se renderizan como tarjetas de vista previa interactivas en etapas con controles explícitos de [Aceptar plan] y [Modificar] antes de confirmar los cambios en el estado de la aplicación. - Calidad basada en el comportamiento: Cada página, componente e interacción se vincula con casos de prueba en lenguaje natural que definen de forma inequívoca el comportamiento esperado.
2. Navegación de la aplicación y jerarquía de vistas
| Ruta de acceso | Nombre de la vista | Propósito principal | Componentes clave incluidos |
|---|---|---|---|
/ |
Redireccionamiento raíz | Redireccionamiento instantáneo a /today. |
(Redireccionamiento del router) |
/today |
Vista previa del entrenamiento de hoy | Vista predeterminada. Se resuelve automáticamente según el día de la semana actual y muestra la vista previa del entrenamiento de hoy. | <BackButton />, <WorkoutHeader />, <CoachNoteCard />, <WorkoutExerciseSummary />, <WorkoutBlock />, <ExerciseCard />, <EmptyDayPlaceholder /> y <ModifyWithCoachCard /> |
/workouts/:day |
Vista previa del entrenamiento diario | Muestra una vista previa del entrenamiento para cualquier día específico de la semana (p.ej., /workouts/monday, /workouts/thursday). |
<BackButton />, <WorkoutHeader />, <CoachNoteCard />, <WorkoutExerciseSummary />, <WorkoutBlock />, <ExerciseCard />, <EmptyDayPlaceholder /> y <ModifyWithCoachCard /> |
/workout/active |
Seguimiento de sesiones activas | Pantalla de ejecución de entrenamiento de alta intensidad (series, repeticiones, temporizador). La barra de navegación inferior permanece visible. | <ActiveSessionStickyHeader />, <ActiveExerciseCardHeader />, <CoachTipCard />, <CurrentSetTargetCard />, <SetNavigationRow />, <ExerciseSetsTable />, <ActiveRestTimerDock />, <SessionExerciseOverview />, <ActiveSessionControlsDock />, <SwapExerciseModal />, <FinishConfirmationModal /> |
/week |
Programa de entrenamiento/vista de semana | Descripción general del programa completo de 7 días con agregaciones semanales de volumen y tiempo | <WeekHeader />, <WeeklyStatsSummary />, <DayScheduleCardList />, <DayScheduleCard /> y <ModifyWeekWithCoachCard /> |
/coach |
Chat del coach potenciado por IA | Asesoramiento conversacional con chips contextuales y propuestas de entrenamiento por etapas. | <CoachHeader />, <ChatMessageList />, <ChatBubble />, <StagedProposalCard />, <ContextualPromptsBar />, <ChatInputDock />, <ContextBanner />, <ChatInputBar />, <SpeechToTextButton /> |
/progress |
Progreso y estadísticas | Registros históricos de entrenamiento, logros de marcas personales y gráficos de volumen. | <ProgressHeader />, <PRShowcaseBanner />, <VolumeProgressChartCard />, <AllTimeStatsGrid />, <WorkoutHistorySection />, <HistorySessionCard />, <EmptyHistoryPlaceholder /> |
/settings |
Perfil y preferencias del usuario | Perfil del equipo, notificaciones y administración de la memoria de 3 niveles. | <SettingsHeader />, <UserProfileCard />, <EquipmentSelectorCard />, <EquipmentToggleChip />, <PreferencesGroup />, <MemoryTierViewerCard />, <MemoryItemCard /> y <AccountActionsGroup /> |
/exercises/:exerciseId |
Detalles de la enciclopedia de ejercicios | Guía de ejercicios con vínculos directos (p. ej., /exercises/incline-db-bench-press) con sugerencias de videos y formularios |
<BackButton />, <ExerciseVideoPlayer />, <TargetMusclesCard />, <HowToPerformCard /> y <FormTipsCard /> |
3. Especificaciones de páginas y vistas
Vista: DailyWorkoutView (/today y /workouts/:day)
- Propósito: Muestra el régimen de entrenamiento programado para un día específico, incluidos el enfoque del entrenamiento, la duración, la distribución de la carga muscular objetivo, las notas del entrenador, los bloques de series rectas y los bloques de superseries, con un estado vacío limpio cuando no hay ningún entrenamiento programado.
- Anatomía visual:
- Arriba:
<BackButton label="Back to Week" targetRoute="/week" />. - Encabezado: Título de una sola línea (
"Today"o día de la semana) con insignia condicional de"✓ Completed", píldora de duración ("⏱ 50 min") y barras de porcentaje de intensidad muscular objetivo. - Nota del entrenador: Tarjeta de consejos contextuales con ícono y borde verde.
- Cuerpo: Lista desplazable de bloques de ejercicio con
<WorkoutExerciseSummary />(series normales o superseries con la insigniaborder-left: 3px solid #a3e635y🔁 SUPERSET BLOCK). - Estado vacío:
<EmptyDayPlaceholder message="Nothing scheduled for this day" />. - Acción del pie de página inferior:
<ModifyWithCoachCard />(enruta a/coach?day=:day).
- Arriba:
Vista: WeekScheduleView (/week)
- Propósito: Muestra un resumen completo del programa de entrenamiento de 7 días, incluidas las métricas generales de volumen y tiempo semanales, una lista seleccionada de días de entrenamiento activos (en la que se filtran estrictamente los días de descanso o no programados) y un acceso directo para revisar el plan semanal con el coach potenciado por IA.
- Anatomía visual:
<WeekHeader />,<WeeklyStatsSummary />de 3 columnas (tiempo total, volumen total y frecuencia), lista de días programados con<DayScheduleCard variant="normal" />(con insigniaTODAYde color verde neón en el día actual) y<ModifyWeekWithCoachCard />(rutas a/coach?context=week).
Vista: CoachChatView (/coach)
- Propósito: Centro de entrenamiento conversacional con el agente de entrenamiento de Gemini. Ofrece consejos de entrenamiento motivacionales y estratégicos, admite el dictado de voz a texto y realiza ajustes de entrenamiento por etapas con intervención humana y controles de aceptación explícitos.
- Anatomía visual:
<CoachHeader />,<ChatMessageList />desplazable (<ChatBubble />y<StagedProposalCard />),<ContextualPromptsBar />condicional y<ChatInputDock />fijado (<ContextBanner />con[✕]para descartar +<ChatInputBar />+<SpeechToTextButton />).
Vista: ExerciseDetailView (/exercises/:exerciseId)
- Propósito: Entrada de enciclopedia con vínculo directo que ofrece una demostración en video silenciado que se reproduce en bucle automáticamente (
<ExerciseVideoPlayer />), insignias de músculos objetivo principales y secundarios (<TargetMusclesCard />), instrucciones de ejecución paso a paso ordenadas (<HowToPerformCard />) y sugerencias de postura (<FormTipsCard />).
Vista: ActiveWorkoutView (/workout/active)
- Propósito: Ejecución de entrenamientos de alta intensidad y pantalla de registro de series. Administra el estado del cronómetro de la sesión en vivo, los objetivos de la serie actual, las entradas de repeticiones y peso, la finalización instantánea de la marca de verificación (<16 ms), la alternancia automática de superseries, las cuentas regresivas del temporizador de descanso con respuesta táctil y audio, el intercambio de ejercicios y la persistencia final en
POST /api/workouts/log. - Anatomía visual:
<ActiveSessionStickyHeader />,<ActiveExerciseCardHeader />,<CoachTipCard />,<CurrentSetTargetCard />,<ActiveRestTimerDock />flotante (+30s,Skip),<SetNavigationRow />,<ExerciseSetsTable />(+ Add Set),<SessionExerciseOverview />,<ActiveSessionControlsDock />fijado ([⇄ SWAP EXERCISE]+[▶ START WORKOUT]/[⏸ PAUSE]/[▶ RESUME]),<SwapExerciseModal />y<FinishConfirmationModal />.
Vista: ProgressView (/progress)
- Propósito: Realiza un seguimiento del progreso atlético a lo largo del tiempo, celebra los récords personales recientes (
<PRShowcaseBanner />), visualiza las tendencias de volumen semanales y mensuales con Recharts interactivos (<VolumeProgressChartCard />con activadores de4W | 3M | 1Y), muestra<AllTimeStatsGrid />y archiva las sesiones de entrenamiento completadas anteriormente (<WorkoutHistorySection />/<HistorySessionCard />).
Vista: SettingsView (/settings)
- Propósito: Administra la información del perfil del atleta (
<UserProfileCard />), el inventario de equipos (<EquipmentSelectorCard />/<EquipmentToggleChip />) y las preferencias de entrenamiento (<PreferencesGroup />paraLBS / KG, respuesta táctil y sonido), y proporciona una administración y eliminación transparentes de los usuarios de la memoria viva de 3 niveles del entrenador de IA (<MemoryTierViewerCard />/<MemoryItemCard />).
4. Catálogo e interfaces de componentes reutilizables
Contratos de propiedades de componentes clave de TypeScript en toda la aplicación:
// src/components/workout/WorkoutExerciseSummary.tsx
interface WorkoutExerciseSummaryProps {
blocks: Array<{
label?: string;
category?: string;
exercises: Array<{
exercise_id: string; // Canonical slug (e.g. 'incline-db-bench-press')
name: string; // Denormalized display name (e.g. 'Incline DB Bench Press')
target_sets: number;
target_reps: string | number;
rest_seconds?: number;
}>;
}>;
activeExerciseId?: string;
onSelectExercise?: (exerciseId: string) => void;
}
// src/components/week/DayScheduleCard.tsx
interface DayScheduleCardProps {
dayName: string;
dayShort: string;
subtitleLabel?: string;
isToday?: boolean;
title: string;
focusBadge: string;
durationMin: number;
volumeLbs?: number;
targetMuscles: string[];
variant?: 'normal' | 'condensed';
onPress: (dayName: string) => void;
}
// src/components/coach/StagedProposalCard.tsx
interface StagedProposalCardProps {
proposalId: string;
type: 'UPDATE_DAY' | 'UPDATE_WEEK';
targetDay?: string;
summaryDiff: string;
proposalData: any;
isApplied?: boolean;
onAccept: (proposalId: string, data: any) => void;
onModify: (summaryDiff: string) => void;
}
// src/components/workout/CurrentSetTargetCard.tsx
interface CurrentSetTargetCardProps {
setNumber: number;
targetWeightLbs: number;
targetReps: number;
isCompleted: boolean;
onWeightChange: (weight: number) => void;
onRepsChange: (reps: number) => void;
onToggleComplete: () => void;
}5. Matriz de administración de estado del cliente y flujo de datos
5.1 Política de latencia y carga: El motor de dos velocidades
- IU optimista en el gimnasio (<16 ms): Las acciones táctiles en el gimnasio, como marcar series, aumentar pesos o repeticiones, cambiar de pestaña y alternar equipos, actualizan el estado local y se vuelven a renderizar en 16 milisegundos. Los usuarios nunca se ven bloqueados por indicadores de carga mientras sostienen pesas.
- Indicadores y controles de carga explícitos para operaciones asíncronas:
- Conversaciones con el entrenador potenciado por IA (
POST /api/coach/chat): Cuando envías un mensaje de chat, se renderiza de inmediato un globo de diálogo animado con un ícono giratorio que indica que el entrenador está pensando en el flujo de chat hasta que Gemini devuelve su respuesta o propuesta de entrenamiento. - Inicio en frío inicial y sincronización de red: Los contenedores de vistas muestran cargadores de esqueleto y controles giratorios de carga de alto contraste mientras se recuperan
weekly_plansohistorical_workouts. - Envío de entrenamiento (
[Finish]): El modal de confirmación de finalización renderiza un ícono giratorio de carga activo mientras la carga útil de la sesión se confirma enPOST /api/workouts/logen Cloud Firestore.
- Conversaciones con el entrenador potenciado por IA (
5.2 Arquitectura de la tienda del cliente y límites de dominio
| Capa de tiendas | Indica el dominio y las propiedades clave | Política de persistencia y almacenamiento en caché | Contrato de backend coordinado |
|---|---|---|---|
useActiveSessionStore (Zustand) |
sessionState (unstarted, running, paused), elapsedSeconds, currentStepIndex, steps: WorkoutStep[], loggedExercises. |
Se sincroniza con localStorage cada segundo para una recuperación infalible de bloqueo y actualización del teléfono. |
Envía la carga útil completada a POST /api/workouts/log. |
useWeeklyPlanQuery (TanStack Query) |
Programa actual de 7 días, objetos de entrenamiento diario, bloques de superseries y estados de finalización (scheduled, completed). |
Se almacena en caché en TanStack Query (staleTime: 5 min) y se recupera previamente en el inicio. |
Se confirma cuando el usuario presiona [Accept Plan] para las propuestas de POST /api/coach/chat. |
useCoachChatStore (Zustand + TanStack) |
Globos de mensajes cronológicos, activeContext, chips de instrucciones, isCoachTyping: boolean, propuestas en etapas. |
Se sincronizó con el bucket de chat semanal de Firestore con la suscripción en tiempo real (onSnapshot). |
Envía consultas a POST /api/coach/chat. |
useProgressQuery (TanStack Query) |
Archivo de entrenamientos históricos, tablero de récords personales (/users/{userId}/prs), agregados de volumen de todos los tiempos, filtro de período (4W, 3M, 1Y). |
Se almacena en caché en TanStack Query (staleTime: 10 min). |
Se actualiza inmediatamente después de completar una sesión de entrenamiento. |
useUserProfileStore (TanStack Query) |
Inventario de equipo, unidades (LBS/KG), interruptores de sonido/hápticos, memoria viva de 3 niveles (básica, fisiológica, situacional). |
Se almacenan en caché en TanStack Query con sincronización bidireccional con Firestore user_profiles. |
Se actualizó de forma autónoma con memory_mutations de POST /api/coach/chat. |
useExerciseLibraryQuery (TanStack Query) |
Entradas estáticas de enciclopedia, URLs de videos, músculos principales y secundarios, pasos, sugerencias de postura. | Almacenamiento en caché agresivo con TTL infinito (staleTime: Infinity). |
Solo lectura de la colección inmutable de Firestore exercises. |
5.3 Gráfico de pasos de la sesión activa calculada previamente
export interface WorkoutStep {
stepIndex: number; // 1-based index (e.g. 1 to 13)
totalSteps: number; // Total sets in the session
blockIndex: number; // Index of block in day plan
blockType: 'straight' | 'superset';
exerciseId: string; // Canonical slug
exerciseName: string; // Display name
setNumber: number; // Set index for this exercise (1, 2, 3...)
targetWeightLbs: number; // Target weight in lbs
targetReps: string | number; // Target reps (e.g. "8-10")
restSecondsAfter: number; // Prescribed rest duration
isCompleted: boolean; // Completion checkmark status
actualWeightLbs?: number; // User entered weight
actualRepsCompleted?: number; // User entered reps
}5.4 Flujo de datos de extremo a extremo y matriz de mutación
| Activador de usuario | Vista de origen | Se modificó el almacén del cliente | Latencia de la IU/Estado de carga | Coordinación del backend | Reversión y manejo de fallas |
|---|---|---|---|---|---|
Presiona [✓] Completar configuración |
/workout/active |
useActiveSessionStore |
<16ms (optimista) |
Se actualizó el búfer de la sesión local; no hay espera de red. | Escritura en la memoria local con persistencia local confiable |
Presiona [Finish Workout]. |
/workout/active |
useActiveSessionStore, useWeeklyPlanStore, useProgressStore |
El botón muestra un ícono giratorio de carga durante la sincronización | Se envía a POST /api/workouts/log. Marca el día de Firestore como completed. |
Si no hay conexión, pone en cola la carga útil en el búfer de sincronización local y vuelve a intentarlo cuando se restablece la conexión. |
Presiona [Accept Plan]. |
/coach |
useWeeklyPlanStore, useCoachChatStore |
Sello de IU instantánea ("✓ Plan Applied") |
Confirma proposal.data en Firestore weekly_plans. |
Si la red falla, una notificación de aviso alerta al usuario y los botones permanecen activos para volver a intentarlo. |
| Envía un mensaje en Chat | /coach |
useCoachChatStore, useUserProfileStore |
Anexión de burbuja optimista + indicador de carga de pensamiento del entrenador | Llamadas POST /api/coach/chat. Se devolvieron memory_mutations confirmaciones. |
Reemplaza el ícono giratorio por "No se pudo enviar. Presiona para volver a intentarlo". |
| Chip de activación de equipo | /settings |
useUserProfileStore |
Botón de activación instantánea (<16ms) |
Envía la escritura en segundo plano a Firestore user_profiles. |
Revierte la selección del chip y muestra un mensaje de error si falla la escritura. |
Borrar elemento de la memoria de IA [🗑] |
/settings |
useUserProfileStore |
Borrado instantáneo (<16ms) |
Envía la mutación de eliminación a Firestore user_profiles. |
Restablece el elemento de memoria y alerta al usuario si falla la eliminación. |
6. Recorridos del usuario de extremo a extremo y matriz de pruebas en lenguaje sencillo
- Paquete 1: Shell de la app, Navigation y Route Handling (pruebas 1.1 a 1.6: redireccionamiento de inicio raíz, panel persistente, retorno rápido de sesión activa, resguardo de día de la semana no válido, resguardo de ruta 404 desconocida, resguardo de vínculo directo de ejercicio no válido).
- Suite 2: Daily Workout View & Block Rendering (pruebas 2.1 a 2.7: resolución dinámica del título del día, ruta de un día específico y botón Atrás, tratamiento de bloques de un solo ejercicio frente a superseries, marcador de posición de día vacío, sello de entrenamiento completado, navegación pura en el botón de reproducción central, modificación con el adjunto de contexto del entrenador).
- Suite 3: Vista de programación semanal y tarjeta de programación diaria (pruebas 3.1 a 3.6: renderización de estadísticas semanales, filtro de solo días programados, texto destacado visual de hoy, navegación por tarjetas de días, modificación de la navegación semanal, renderización de variantes condensadas).
- Suite 4: Coach Chat & Staged Mutation (pruebas 4.1 a 4.7: renderización del flujo de mensajes de chat, adjunto y descarte del banner de contexto, prepropagación de chips de instrucciones, activación/desactivación de dictado de voz, aislamiento de mutaciones en etapas, aceptación y confirmación de propuestas, vista previa y confirmación de propuestas de revisión semanal).
- Suite 5: Exercise Detail & Encyclopedia (pruebas 5.1 a 5.5: renderización de detalles de ejercicios, reproducción silenciada en bucle automático, activación/desactivación de pausa de video, etiquetas de músculos primarios y secundarios, navegación hacia atrás en el historial y resguardo).
- Suite 6: Active Workout Tracker & Logging (pruebas 6.1 a 6.7: estado inicial no iniciado y cronómetro de inicio, pausa y reanudación manuales, registro de series táctiles y activación/desactivación de marcas de verificación, alternancia de pasos de superconjunto, modal de intercambio de ejercicios y reemplazo, confirmación de finalización y sincronización con el servidor, recuperación del estado de la sesión al volver a cargar).
- Suite 7: Progress & Historical Analytics (pruebas 7.1 a 7.5: renderización de la descripción general del panel de progreso, visualización del banner de presentación de PR, activación o desactivación del período del gráfico, estado de historial vacío, presión del historial de sesiones anteriores).
- Suite 8: Configuración del usuario, equipo y memoria de IA (pruebas 8.1 a 8.4: renderización de la vista de configuración, actualización del botón de activación del equipo, cambio de unidades, eliminación de elementos de la memoria de IA).