Smart Fitness App: Client Architecture Spec
ArtefattoQuesto è l'artefatto utilizzato nell'episodio 3: Give Your App a Brain e nell'episodio 4: The No-Code App Implementation Plan. Puoi utilizzare questa specifica come riferimento per le visualizzazioni frontend, i componenti UI riutilizzabili, la gestione dello stato del client e gli scenari di test in linguaggio naturale.
Accedi per visualizzare questo artefatto
Accedi con il tuo Profilo sviluppatore Google per visualizzare e copiare l'artefatto completo utilizzato nella serie Build It!.
Profilo sviluppatore richiesto
Non hai l'idoneità per un profilo sviluppatore. Chiedi all'amministratore di Workspace di attivare questa funzionalità.
Crea un Profilo sviluppatore
Crea un profilo sviluppatore Google senza costi per sbloccare tutti i prompt e gli artefatti di Build It!
Iscriviti a Builder Central per sbloccare
Richiedi il tuo badge per gli abbonati Builder senza costi con un solo clic per sbloccare tutti i prompt e gli artefatti di Build It!.
Stato: pronto per la sessione di pianificazione (bozza con il compagno di pianificazione del cliente)
Documento complementare: Specifica dell'architettura dei dati
Obiettivo dell'architettura: ricostruzione del frontend pulita, gestibile, modulare e testabile del prototipo di fitness smart di AI Studio.
0. Stack tecnico di base e standard di ingegneria
- Framework di runtime: Next.js (App Router, React 19) + memorizzazione nella cache degli asset offline dell'app web progressiva (PWA).
- Architettura di stile: Tailwind CSS v4 + Tailwind Variants (per lo stile dei componenti deterministici) + Lucide React (icone).
- Client State Division:
- Zustand (sessione locale): gestisce lo stato volatile della palestra (
useActiveSessionStore), i timer del cronometro, i buffer dei set attivi e la sequenza dei passaggi precalcolati. Sincronizzato conlocalStorageper il recupero del blocco dello smartphone. - TanStack Query (stato del server): gestisce la memorizzazione nella cache dei documenti Firestore, la riconvalida in background e gli aggiornamenti ottimistici per
weekly_plans,user_profiles,prseworkout_logs.
- Zustand (sessione locale): gestisce lo stato volatile della palestra (
- Visualizzazione dei grafici: Recharts (con stile personalizzato con token in modalità palestra scura).
- Autenticazione: Firebase Authentication con intestazione di autenticazione del token di connessione passata a tutti gli endpoint del server.
1. Principi di progettazione e principi di frontend
- Ergonomia pensata per la palestra: progettati per un utilizzo tattile con una sola mano durante l'allenamento, anche con le mani sudate. Touch target ampi (minimo 48 x 48 dp), leggibilità ad alto contrasto e digitazione minima richiesta.
- Interfaccia utente ottimistica e resilienza offline: la registrazione delle serie, l'avvio dei timer di riposo e lo scambio di esercizi devono rispondere istantaneamente (<16 ms) nell'interfaccia utente. La sincronizzazione in background gestisce la persistenza del server su
POST /api/workouts/logsenza bloccare l'utente. - Separazione rigorosa delle responsabilità: i componenti dumb/presentational ricevono dati ed emettono eventi utilizzando le proprietà; le visualizzazioni dei container smart gestiscono la logica di business, gli archivi di stato e il coordinamento delle API.
- UX di mutazione in fasi: i suggerimenti generati dal coach AI (
POST /api/coach/chat) vengono visualizzati come schede di anteprima interattive in fasi con controlli espliciti [Accetta piano] e [Modifica] prima di applicare le modifiche allo stato dell'applicazione. - Qualità basata sul comportamento: ogni pagina, componente e interazione è associato a scenari di test in un linguaggio semplice che definiscono in modo inequivocabile il comportamento previsto.
2. Navigazione nell'applicazione e gerarchia di oggetti View
| Percorso della route | Nome vista | Scopo principale | Componenti chiave contenuti |
|---|---|---|---|
/ |
Reindirizzamento root | Reindirizzamento istantaneo a /today. |
(Reindirizzamento del router) |
/today |
Anteprima dell'allenamento di oggi | Visualizzazione predefinita. Si risolve automaticamente nel giorno della settimana corrente e visualizza l'anteprima dell'allenamento di oggi. | <BackButton />, <WorkoutHeader />, <CoachNoteCard />, <WorkoutExerciseSummary />, <WorkoutBlock />, <ExerciseCard />, <EmptyDayPlaceholder />, <ModifyWithCoachCard /> |
/workouts/:day |
Anteprima dell'allenamento giornaliero | Mostra l'anteprima dell'allenamento per un giorno specifico della settimana (ad es. /workouts/monday, /workouts/thursday). |
<BackButton />, <WorkoutHeader />, <CoachNoteCard />, <WorkoutExerciseSummary />, <WorkoutBlock />, <ExerciseCard />, <EmptyDayPlaceholder />, <ModifyWithCoachCard /> |
/workout/active |
Tracker delle sessioni attive | Schermata di esecuzione dell'allenamento ad alto rischio (serie, ripetizioni, timer). La navigazione in basso rimane visibile. | <ActiveSessionStickyHeader />, <ActiveExerciseCardHeader />, <CoachTipCard />, <CurrentSetTargetCard />, <SetNavigationRow />, <ExerciseSetsTable />, <ActiveRestTimerDock />, <SessionExerciseOverview />, <ActiveSessionControlsDock />, <SwapExerciseModal />, <FinishConfirmationModal /> |
/week |
Programma di allenamento/Visualizzazione settimana | Panoramica completa della programmazione di 7 giorni con aggregati settimanali di volume/tempo. | <WeekHeader />, <WeeklyStatsSummary />, <DayScheduleCardList />, <DayScheduleCard />, <ModifyWeekWithCoachCard /> |
/coach |
Chat con il coach AI | Coaching conversazionale con chip contestuali e proposte di allenamento graduali. | <CoachHeader />, <ChatMessageList />, <ChatBubble />, <StagedProposalCard />, <ContextualPromptsBar />, <ChatInputDock />, <ContextBanner />, <ChatInputBar />, <SpeechToTextButton /> |
/progress |
Progressi e analisi | Log di allenamento storici, record personali e grafici del volume. | <ProgressHeader />, <PRShowcaseBanner />, <VolumeProgressChartCard />, <AllTimeStatsGrid />, <WorkoutHistorySection />, <HistorySessionCard />, <EmptyHistoryPlaceholder /> |
/settings |
Profilo utente e preferenze | Profilo dell'attrezzatura, notifiche e gestione della memoria a 3 livelli. | <SettingsHeader />, <UserProfileCard />, <EquipmentSelectorCard />, <EquipmentToggleChip />, <PreferencesGroup />, <MemoryTierViewerCard />, <MemoryItemCard />, <AccountActionsGroup /> |
/exercises/:exerciseId |
Dettagli dell'enciclopedia degli esercizi | Guida agli esercizi con link diretti (ad es. /exercises/incline-db-bench-press) con video e suggerimenti sulla postura. |
<BackButton />, <ExerciseVideoPlayer />, <TargetMusclesCard />, <HowToPerformCard />, <FormTipsCard /> |
3. Specifiche di pagine e visualizzazioni
Visualizzazione: DailyWorkoutView (/today e /workouts/:day)
- Scopo: mostra il programma di allenamento pianificato per un giorno specifico, inclusi il focus dell'allenamento, la durata, la distribuzione del carico muscolare target, le note del coach, i blocchi di serie semplici e i blocchi di superset, con un fallback di stato vuoto pulito quando non è pianificato alcun allenamento.
- Anatomia visiva:
- Superiore:
<BackButton label="Back to Week" targetRoute="/week" />. - Intestazione: titolo su una riga (
"Today"o giorno della settimana) con badge"✓ Completed"condizionale, pillola della durata ("⏱ 50 min") e barre della percentuale di intensità muscolare target. - Nota del coach: scheda di suggerimenti contestuali con icona e bordo verde.
- Corpo: elenco scorrevole di blocchi di esercizi che utilizzano
<WorkoutExerciseSummary />(set singoli o superset con badgeborder-left: 3px solid #a3e635e🔁 SUPERSET BLOCK). - Stato vuoto:
<EmptyDayPlaceholder message="Nothing scheduled for this day" />. - Azione del piè di pagina:
<ModifyWithCoachCard />(indirizza a/coach?day=:day).
- Superiore:
Visualizzazione: WeekScheduleView (/week)
- Scopo: mostra la panoramica completa del programma di allenamento di 7 giorni, incluse le metriche di volume/tempo settimanali di alto livello, un elenco selezionato di giorni di allenamento attivi (filtrando rigorosamente i giorni non programmati/di riposo) e una scorciatoia diretta per rivedere il piano settimanale con il coach AI.
- Anatomia visiva:
<WeekHeader />,<WeeklyStatsSummary />a 3 colonne (Tempo totale, Volume totale, Frequenza), elenco dei giorni programmati utilizzando<DayScheduleCard variant="normal" />(con badgeTODAYverde neon sul giorno corrente) e<ModifyWeekWithCoachCard />(percorso verso/coach?context=week).
Visualizzazione: CoachChatView (/coach)
- Scopo: hub di coaching conversazionale con l'agente Gemini Trainer. Fornisce consigli di allenamento motivazionali e strategici, supporta la dettatura da voce a testo e consente di apportare modifiche agli allenamenti in più fasi con human-in-the-loop e controlli di accettazione espliciti.
- Anatomia visiva:
<CoachHeader />,<ChatMessageList />scorrevole (<ChatBubble />e<StagedProposalCard />),<ContextualPromptsBar />condizionale e<ChatInputDock />ancorato (<ContextBanner />con chiusura[✕]+<ChatInputBar />+<SpeechToTextButton />).
Visualizzazione: ExerciseDetailView (/exercises/:exerciseId)
- Scopo: voce di enciclopedia con link diretto che fornisce una dimostrazione video disattivata in loop automatico (
<ExerciseVideoPlayer />), badge dei muscoli target principali e secondari (<TargetMusclesCard />), istruzioni di esecuzione passo passo ordinate (<HowToPerformCard />) e suggerimenti sulla forma (<FormTipsCard />).
Visualizzazione: ActiveWorkoutView (/workout/active)
- Scopo: schermata di esecuzione di allenamenti ad alta intensità e registrazione delle serie. Gestisce lo stato del cronometro della sessione in tempo reale, i target dei set correnti, gli input di ripetizioni/peso, il completamento istantaneo del segno di spunta (<16 ms), l'alternanza automatica dei superset, i timer di riposo con feedback aptico/audio, lo scambio di esercizi e la persistenza finale in
POST /api/workouts/log. - Anatomia visiva:
<ActiveSessionStickyHeader />,<ActiveExerciseCardHeader />,<CoachTipCard />,<CurrentSetTargetCard />,<ActiveRestTimerDock />mobile (+30s,Skip),<SetNavigationRow />,<ExerciseSetsTable />(+ Add Set),<SessionExerciseOverview />,<ActiveSessionControlsDock />ancorato ([⇄ SWAP EXERCISE]+[▶ START WORKOUT]/[⏸ PAUSE]/[▶ RESUME]),<SwapExerciseModal />e<FinishConfirmationModal />.
Visualizzazione: ProgressView (/progress)
- Scopo: monitora i progressi atletici nel tempo, celebra i record personali recenti (
<PRShowcaseBanner />), visualizza le tendenze del volume settimanale/mensile con Recharts interattivi (<VolumeProgressChartCard />con pulsanti di attivazione/disattivazione4W | 3M | 1Y), mostra<AllTimeStatsGrid />e archivia le sessioni di allenamento completate in passato (<WorkoutHistorySection />/<HistorySessionCard />).
Visualizzazione: SettingsView (/settings)
- Scopo: gestisce le informazioni del profilo dell'atleta (
<UserProfileCard />), l'inventario dell'attrezzatura (<EquipmentSelectorCard />/<EquipmentToggleChip />), le preferenze di allenamento (<PreferencesGroup />perLBS / KG, feedback aptico, audio) e fornisce una gestione trasparente degli utenti e l'eliminazione della memoria attiva a 3 livelli del trainer AI (<MemoryTierViewerCard />/<MemoryItemCard />).
4. Catalogo e interfacce dei componenti riutilizzabili
Contratti delle proprietà dei componenti TypeScript chiave nell'applicazione:
// 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. Matrice di gestione dello stato del client e del flusso di dati
5.1 Norme relative a latenza e caricamento: il motore a due velocità
- UI ottimistica per la palestra (<16 ms): le azioni tattili in palestra, come spuntare le serie, aumentare i pesi/le ripetizioni, cambiare scheda e attivare/disattivare l'attrezzatura, aggiornano lo stato locale ed eseguono il rendering entro 16 millisecondi. Gli utenti non vengono mai bloccati dagli indicatori di caricamento mentre tengono i pesi.
- Indicatori e spinner di caricamento espliciti per le operazioni asincrone:
- Conversazioni con il coach AI (
POST /api/coach/chat): l'invio di un messaggio chat genera immediatamente un fumetto con un'icona di caricamento animata che indica che il coach sta pensando nel flusso della chat finché Gemini non restituisce la risposta o la proposta di allenamento. - Avvio a freddo iniziale e sincronizzazione di rete: i contenitori di visualizzazione mostrano scheletri di caricamento e indicatori di caricamento ad alto contrasto durante il recupero di
weekly_plansohistorical_workouts. - Invio dell'allenamento (
[Finish]): la finestra modale di conferma della fine mostra un indicatore di caricamento attivo mentre il payload della sessione viene inviato aPOST /api/workouts/login Cloud Firestore.
- Conversazioni con il coach AI (
5.2 Architettura del negozio del cliente e confini del dominio
| Livello negozio | Stato del dominio e proprietà chiave | Policy di persistenza e cache | Contratto di backend coordinato |
|---|---|---|---|
useActiveSessionStore (Zustand) |
sessionState (unstarted, running, paused), elapsedSeconds, currentStepIndex, steps: WorkoutStep[], loggedExercises. |
Sincronizzato con localStorage ogni secondo per un recupero infallibile del blocco/aggiornamento dello smartphone. |
Invia il payload completato a POST /api/workouts/log. |
useWeeklyPlanQuery (TanStack Query) |
Programma attuale di 7 giorni, oggetti di allenamento giornalieri, blocchi di superset, stati di completamento (scheduled, completed). |
Memorizzato nella cache in TanStack Query (staleTime: 5 min); precaricato al lancio. |
Impegnato quando l'utente tocca [Accept Plan] per le proposte di POST /api/coach/chat. |
useCoachChatStore (Zustand + TanStack) |
Bolle di messaggio cronologiche, activeContext, chip di prompt, isCoachTyping: boolean, proposte in fasi. |
Sincronizzato con il bucket di chat settimanale di Firestore utilizzando l'abbonamento in tempo reale (onSnapshot). |
Invia le query a POST /api/coach/chat. |
useProgressQuery (TanStack Query) |
Archivio degli allenamenti storici, bacheca dei record personali (/users/{userId}/prs), aggregati del volume di tutti i tempi, filtro del periodo di tempo (4W, 3M, 1Y). |
Memorizzato nella cache in TanStack Query (staleTime: 10 min). |
Aggiornato immediatamente al termine di una sessione di allenamento. |
useUserProfileStore (TanStack Query) |
Inventario dell'attrezzatura, unità (LBS/KG), pulsanti di attivazione/disattivazione di suoni/feedback aptico, memoria attiva a 3 livelli (Elementi di base, Fisiologici, Situazionali). |
Memorizzati nella cache in TanStack Query con sincronizzazione bidirezionale con Firestore user_profiles. |
Aggiornamento autonomo utilizzando memory_mutations da POST /api/coach/chat. |
useExerciseLibraryQuery (TanStack Query) |
Voci enciclopediche statiche, URL dei video, muscoli primari/secondari, passaggi, suggerimenti sulla forma. | Aggressive cache-first with infinite TTL (staleTime: Infinity). |
Sola lettura dalla raccolta Firestore exercises immutabile. |
5.3 Grafico dei passi della sessione di attività precalcolata
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 Matrice di mutazione e flusso di dati end-to-end
| Trigger utente | Vista di origine | Client Store Mutated | Latenza UI/Stato di caricamento | Coordinamento del backend | Rollback/Gestione degli errori |
|---|---|---|---|---|---|
Tocca [✓] Set completo |
/workout/active |
useActiveSessionStore |
<16ms (ottimistico) |
Buffer della sessione locale aggiornato; nessuna attesa di rete. | Scrittura nella memoria locale con persistenza locale affidabile. |
Tocca [Finish Workout] |
/workout/active |
useActiveSessionStore, useWeeklyPlanStore e useProgressStore |
Il pulsante mostra l'icona di caricamento durante la sincronizzazione | Invia a POST /api/workouts/log. Contrassegna il giorno di Firestore come completed. |
Se offline, mette in coda il payload nel buffer di sincronizzazione locale e riprova al momento della riconnessione. |
Tocca [Accept Plan] |
/coach |
useWeeklyPlanStore, useCoachChatStore |
Bollino UI istantanea ("✓ Plan Applied") |
Esegue il commit di proposal.data in Firestore weekly_plans. |
Se la rete non funziona, una notifica toast avvisa l'utente e i pulsanti rimangono attivi per riprovare. |
| Invia un messaggio in Chat | /coach |
useCoachChatStore, useUserProfileStore |
Aggiunta di un fumetto ottimistico + indicatore di caricamento del pensiero di Coach | Chiamate POST /api/coach/chat. Commit restituiti: memory_mutations. |
Sostituisce l'indicatore di rotazione con "Invio non riuscito. Tocca per riprovare". |
| Attiva/disattiva il chip Attrezzatura | /settings |
useUserProfileStore |
Attivazione/disattivazione istantanea (<16ms) |
Invia la scrittura in background a Firestore user_profiles. |
Ripristina la selezione del chip e visualizza un messaggio di errore se la scrittura non va a buon fine. |
Elimina elemento della memoria AI [🗑] |
/settings |
useUserProfileStore |
Eliminazione istantanea (<16ms) |
Invia la mutazione di eliminazione a Firestore user_profiles. |
Ripristina l'elemento della memoria e avvisa l'utente se l'eliminazione non va a buon fine. |
6. User journey end-to-end e matrice di test in linguaggio naturale
- Suite 1: shell dell'app, navigazione e gestione dei percorsi (test 1.1-1.6: reindirizzamento del lancio principale, dock permanente, ritorno rapido alla sessione di attività attiva, fallback per giorno della settimana non valido, fallback 404 per percorso sconosciuto, fallback per deep link di allenamento non valido).
- Suite 2: Daily Workout View & Block Rendering (Test 2.1–2.7: Dynamic day title resolution, specific day route & pulsante Indietro, single versus superset block treatment, empty day placeholder, completed workout stamp, pure navigation on center play button, modify with coach context attachment).
- Suite 3: visualizzazione del programma settimanale e scheda del programma giornaliero (test 3.1-3.6: rendering delle statistiche settimanali, filtro solo per i giorni programmati, callout visivo di oggi, navigazione della scheda del giorno, modifica della navigazione della settimana, rendering della variante condensata).
- Suite 4: Coach Chat & Staged Mutation (test 4.1-4.7: rendering del flusso di messaggi chat, aggiunta e chiusura del banner di contesto, precompilazione dei chip di prompt, attivazione/disattivazione della dettatura vocale, isolamento della mutazione in fasi, accettazione e commit della proposta, anteprima e commit della proposta di revisione settimanale).
- Suite 5: Dettagli sull'esercizio ed enciclopedia (test 5.1-5.5: rendering dei dettagli sull'esercizio, riproduzione in loop automatico con audio disattivato, attivazione/disattivazione della pausa video, tag dei muscoli principali e secondari, navigazione a ritroso nella cronologia e fallback).
- Suite 6: Active Workout Tracker & Logging (Test 6.1–6.7: Unstarted initial state & manual start, pause and resume stopwatch, tactile set logging & checkmark toggle, superset step alternation, swap exercise modal & replacement, finish confirmation & server sync, session state recovery on reload).
- Suite 7: Progress & Historical Analytics (Test 7.1-7.5: rendering della panoramica della dashboard dei progressi, visualizzazione del banner di presentazione di PR, attivazione/disattivazione del periodo di tempo del grafico, stato della cronologia vuoto, tocco della cronologia delle sessioni passate).
- Suite 8: User Settings, Equipment & AI Memory (Test 8.1-8.4: rendering della visualizzazione delle impostazioni, aggiornamento dell'opzione di attivazione/disattivazione dell'attrezzatura, cambio di unità, eliminazione di elementi della memoria AI).