Files
traccia-calorica/docs/TECHNICAL.md
emanuele 7fd03a99ba chore: initial project setup with documentation and design assets
Add project foundation: CLAUDE.md, requirements tracking system,
technical architecture docs, Firestore setup guide, device testing guide,
and Stitch design mockups for Precision Vitality app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 09:44:35 +02:00

9.0 KiB

Requisiti Tecnici — CalorieTracker (Precision Vitality)

Documento di architettura e decisioni tecniche del progetto. Ultimo aggiornamento: 16/04/2026


1. Panoramica Architettura

┌─────────────────────────────────────────────┐
│            App Ionic/Angular                │
│  ┌───────────┐  ┌───────────┐  ┌─────────┐ │
│  │  Journal   │  │   Stats   │  │ Search  │ │
│  │  (Home)    │  │ Day/Week  │  │         │ │
│  └─────┬─────┘  └─────┬─────┘  └────┬────┘ │
│        │               │             │       │
│  ┌─────┴───────────────┴─────────────┴────┐ │
│  │         Core Services Layer            │ │
│  │  MealService | CalorieEstimator | Auth │ │
│  └─────┬───────────────┬─────────────────┘ │
│        │               │                    │
└────────┼───────────────┼────────────────────┘
         │               │
    ┌────┴────┐   ┌──────┴──────┐
    │Firestore│   │ Firebase CF │
    │  (DB)   │   │  (Proxy AI) │
    └─────────┘   └──────┬──────┘
                         │
                  ┌──────┴──────┐
                  │ Anthropic   │
                  │ Claude API  │
                  └─────────────┘

2. Stack Tecnologico

Layer Tecnologia Versione Motivazione
Framework UI Ionic 7+ Cross-platform, componenti nativi
Framework App Angular 17+ Standalone components, signals
Mobile Runtime Capacitor 5+ Build nativo Android/iOS
Database Firebase Firestore 10+ Free tier, offline, real-time
Auth Firebase Auth 10+ Anonymous + Google Sign-In
AI Proxy Firebase Cloud Functions Gen2 Free tier, sicurezza API key
AI Model Claude Haiku 4.5 claude-haiku-4-5-20251001 Economico, veloce, sufficiente per stime
Chart Chart.js + ng2-charts 4+ Leggero (~200KB), well-maintained
Storage locale @ionic/storage-angular 4+ Preferenze utente (obiettivo kcal)
Linguaggio TypeScript 5.3+ Type safety

3. Requisiti Ambiente di Sviluppo

Requisito Versione Minima Note
Node.js 18+ LTS raccomandato
npm 9+ Incluso con Node.js
Ionic CLI 7+ npm i -g @ionic/cli
Angular CLI 17+ Incluso come dipendenza
Java JDK 17+ Per build Android (Gradle)
Android SDK API 33+ Per build APK

4. Configurazione Variabili d'Ambiente

environment.ts (development)

export const environment = {
  production: false,
  firebase: {
    apiKey: '...',
    authDomain: '...',
    projectId: '...',
    storageBucket: '...',
    messagingSenderId: '...',
    appId: '...'
  },
  cloudFunctionUrl: 'http://localhost:5001/PROJECT_ID/us-central1/estimateCalories',
  defaultCalorieTarget: 2000
};

environment.prod.ts (production)

export const environment = {
  production: true,
  firebase: { /* config produzione */ },
  cloudFunctionUrl: 'https://us-central1-PROJECT_ID.cloudfunctions.net/estimateCalories',
  defaultCalorieTarget: 2000
};

IMPORTANTE: I file environment.*.ts sono nel .gitignore. Usare environment.example.ts come template.


5. Firebase Cloud Function — Proxy AI

Architettura

Client → Cloud Function → Anthropic API → Cloud Function → Client

Endpoint

  • URL: POST /estimateCalories
  • Body: { description: string }
  • Response: { calories: number, confidence: 'high'|'medium'|'low', explanation: string }
  • Auth: Firebase Auth token required (header Authorization: Bearer <token>)

Implementazione Cloud Function

// functions/src/index.ts
import { onRequest } from 'firebase-functions/v2/https';
import Anthropic from '@anthropic-ai/sdk';

export const estimateCalories = onRequest(
  { cors: true, region: 'europe-west1' },
  async (req, res) => {
    // 1. Verificare Firebase Auth token
    // 2. Estrarre description dal body
    // 3. Chiamare Claude con food dictionary nel system prompt
    // 4. Parsare risposta JSON
    // 5. Restituire risultato
  }
);

Sicurezza

  • API key Anthropic in Secret Manager di Firebase
  • Rate limiting: max 10 richieste/minuto per utente
  • Validazione input: description max 500 caratteri
  • Timeout: 10 secondi

6. Schema Dati Firestore

Collection users/{userId}/meals/{mealId}

Campo Tipo Obbligatorio Descrizione
id string Auto-generated document ID
timestamp Timestamp Data/ora del pasto
calories number Kcal totali
inputType string 'manual' o 'llm'
description string No Descrizione testuale
llmConfidence string No 'high', 'medium', 'low' (solo se llm)
llmExplanation string No Spiegazione AI (solo se llm)
createdAt Timestamp Data creazione documento

Indici Richiesti

Collection: users/{userId}/meals
  - (timestamp DESC) — per query giornaliere e range

7. Servizi Angular Core

AuthService

- signInAnonymously(): Promise<User>
- getCurrentUser(): Observable<User | null>
- getUserId(): string

MealService

- addMeal(data: MealInput): Promise<string>
- getMealsForDate(date: Date): Observable<Meal[]>
- getMealsInRange(from: Date, to: Date): Observable<Meal[]>
- deleteMeal(mealId: string): Promise<void>
- getTotalCaloriesForDate(date: Date): Observable<number>

CalorieEstimatorService

- estimateCalories(description: string): Observable<CalorieEstimate>

StorageService

- getCalorieTarget(): Promise<number>
- setCalorieTarget(target: number): Promise<void>

8. Interfacce TypeScript

interface Meal {
  id: string;
  timestamp: Date;
  calories: number;
  inputType: 'manual' | 'llm';
  description?: string;
  llmConfidence?: 'high' | 'medium' | 'low';
  llmExplanation?: string;
  createdAt: Date;
}

interface MealInput {
  calories: number;
  inputType: 'manual' | 'llm';
  description?: string;
  llmConfidence?: 'high' | 'medium' | 'low';
  llmExplanation?: string;
}

interface CalorieEstimate {
  calories: number;
  confidence: 'high' | 'medium' | 'low';
  explanation: string;
}

9. Design System — Mapping Tecnico

Colori (CSS Custom Properties)

:root {
  --pv-primary: #006b1b;
  --pv-primary-dim: #005d16;
  --pv-accent: #FF7043;
  --pv-error: #F44336;
  --pv-surface: #f6f6f6;
  --pv-surface-container-low: #f0f1f1;
  --pv-surface-container-lowest: #ffffff;
  --pv-on-surface: #2d2f2f;
  --pv-on-surface-variant: #757575;
}

Font (da importare)

@import url('https://fonts.googleapis.com/css2?family=Lexend:wght@400;700&family=Plus+Jakarta+Sans:wght@400;500;600&display=swap');

:root {
  --pv-font-data: 'Lexend', sans-serif;
  --pv-font-ui: 'Plus Jakarta Sans', sans-serif;
}

Regole Chiave

  1. No borders — separazione solo via background shifts
  2. No drop shadows su card — usare tonal layering
  3. Border radius: 1.5rem (card principali), 1rem (elementi nested)
  4. Spacing: 24px vertical padding nelle card
  5. Progress bar: 12px altezza, full roundedness, gradient primary-fixed → primary
  6. FAB: gradient primary → primary-dim a 135°, shadow 0px 12px 32px rgba(0,107,27,0.15)

10. Performance e Limiti

Firestore (Spark Plan — Gratuito)

  • 50.000 letture/giorno
  • 20.000 scritture/giorno
  • 1 GiB storage
  • 10 GiB trasferimento/mese

Claude API (Haiku)

  • ~$0.25 per 1M input tokens
  • ~$1.25 per 1M output tokens
  • Stima: ~$0.001 per richiesta singola
  • Budget suggerito: $5/mese per uso moderato

Ottimizzazioni

  • Cache locale food dictionary (caricato una volta)
  • Observable Firestore per real-time (no polling)
  • Lazy loading moduli Angular
  • Offline persistence Firestore per uso senza rete

11. Sicurezza

Rischio Mitigazione
API key Anthropic esposta Firebase Cloud Function come proxy
Accesso dati cross-user Firestore Security Rules basate su userId
Input injection nell'LLM Sanitizzazione input + max 500 caratteri
Firebase config nel bundle Le Firebase config sono safe da esporre (solo project identifier)
Rate abuse Rate limiting nella Cloud Function (10 req/min/user)