--- stepsCompleted: ['step-01-init', 'step-02-context', 'step-03-starter', 'step-04-decisions', 'step-05-patterns', 'step-06-structure'] inputDocuments: - prd.md workflowType: 'architecture' project_name: 'chartbastan' user_name: 'Ramez' date: '2026-01-15T21:00:00.000Z' lastStep: 8 status: 'complete' completedAt: '2026-01-15T22:00:00.000Z' --- # Architecture Decision Document _This document builds collaboratively through step-by-step discovery. Sections are appended as we work through each architectural decision together._ ## Project Context Analysis ### Requirements Overview **Functional Requirements:** Le projet chartbastan est une application web de prédiction de résultats de football basée sur l'analyse de l'énergie collective des supporters via les réseaux sociaux. Les exigences fonctionnelles principales incluent : - **Collecte de données multi-sources** : Scraping Twitter (60%), Reddit (25%), RSS (15%) avec pondération intelligente - **Analyse de sentiment en temps réel** : Utilisation de VADER/textblob pour analyser 1000+ tweets en < 1 seconde - **Calcul d'énergie collective** : Formule Score = (Positif - Négatif) × Volume × Viralité avec pondération temporelle - **Système de backtesting** : Validation sur 100+ matchs historiques avec seuil de précision ≥ 60% - **Dashboard temps réel** : Visualisations interactives (D3.js) avec Confidence Meter (0-100%) - **Gamification** : Système de classement, badges, parrainage (invite 3 amis = 1 mois premium gratuit) - **Modèle freemium** : Version gratuite (1-2 prédictions/jour) + Premium (19.99€/mois) avec métriques avancées - **API publique** : Documentation et accès pour développeurs tiers (Phase 2+) - **Notifications push** : Alertes pour changements majeurs d'énergie collective **Non-Functional Requirements:** Les NFRs critiques qui façonneront l'architecture : - **Performance** : Dashboard mis à jour en < 3 secondes, analyse de 1000+ tweets en < 1 seconde - **Disponibilité** : Uptime > 99.5% pour l'API FastAPI principale - **Scalabilité** : Système de queue asynchrone (RabbitMQ) pour gérer les pics de charge - **Précision** : Taux de précision ≥ 60% (seuil de validation, < 55% = révision requise) - **Rate limiting** : Gestion robuste des limites API Twitter (1000 req/heure gratuit) - **Qualité frontend** : Next.js 16 responsive avec Lighthouse score > 90 - **Fiabilité** : Scraping Twitter stable sur 24h sans interruption - **Transparence** : Confidence Meter précis à ±5% du taux de réussite réel **Scale & Complexity:** - **Primary domain** : Full-stack web application (Next.js 16 frontend + FastAPI backend) - **Complexity level** : High (classification PRD) - **Estimated architectural components** : ~11 composants majeurs - Service de scraping multi-sources - Service d'analyse de sentiment - Service de calcul d'énergie - API backend (FastAPI) - API frontend (Next.js API routes) - Dashboard frontend (Next.js + D3.js) - Système de queue (RabbitMQ) - Base de données (SQLite Phase 1) - Service de notifications - Système d'authentification/autorisation - Service de backtesting ### Technical Constraints & Dependencies **Contraintes budgétaires Phase 1 :** - Budget minimal : 10-20€/mois - SQLite (gratuit) suffisant pour Phase 1 - API Twitter gratuite (1000 req/heure) - Pas d'app mobile complexe (web responsive suffisant) **Stack technique imposé :** - Frontend : Next.js 16 + Tailwind 4 + shadcn/ui - Backend primaire : Python FastAPI (analytics, ML, sentiment analysis) - Backend secondaire : Node.js (Next.js API routes pour API légère, authentification) - Base de données : SQLite (Phase 1) → migration future prévue - Queue : RabbitMQ pour traitement asynchrone **Dépendances externes critiques :** - Twitter API (rate limit : 1000 req/heure) - Reddit API (généreuse, pas de rate limiting strict) - RSS Feeds (diverses sources) - Mailchimp (gratuit pour capture emails Phase 1) **Contraintes de domaine :** - Focus unique sur Football pour Phase 1 - Domaine gambling/betting (implications compliance potentielles) - Projet greenfield (nouveau développement) ### Cross-Cutting Concerns Identified **Gestion des API externes :** - Rate limiting et priorisation dynamique (matchs VIP vs autres) - Gestion des pannes (modes dégradés : Reddit + RSS uniquement) - Monitoring et alertes prédictives (> 90% utilisation) - Optimisation intelligente (scraper tweets avec engagement élevé) **Traitement asynchrone :** - Queue RabbitMQ pour découpler scraping et analyse - Gestion des pics de charge (événements majeurs) - Traitement batch pour backtesting **Temps réel :** - Dashboard avec mises à jour en temps réel - Notifications push pour changements majeurs - Visualisations dynamiques (D3.js) **Multi-tenant :** - Différenciation gratuit/premium (features, SLA, rate limiting) - Système d'authentification/autorisation - Métriques et analytics différenciés **Compliance & Transparence :** - Domaine gambling/betting (réglementations potentielles) - Transparence algorithmique (explication des prédictions) - Documentation publique des résultats (Medium, Reddit) ## Starter Template Evaluation ### Primary Technology Domain Full-stack web application basé sur l'analyse du contexte projet et des exigences. ### Starter Options Considered **Option 1 : create-next-app (officiel Next.js)** - Starter officiel Next.js 16 avec support App Router, TypeScript, Tailwind CSS, ESLint/Biome - Turbopack activé par défaut pour un bundling rapide - Structure modulaire avec `src/` directory - Intégration shadcn/ui via CLI séparé **Option 2 : shadcn/ui CLI (canary pour Tailwind v4)** - Compatible Tailwind v4 + React 19 - Intégration native avec Next.js 16 - Style "new-york" par défaut - Composants copiés dans le projet (pas de dépendance externe) ### Selected Starter: create-next-app + shadcn/ui **Rationale for Selection:** Approche en deux étapes recommandée : 1. `create-next-app` pour établir la base Next.js 16 avec toutes les configurations essentielles 2. `shadcn@canary` pour intégrer l'UI avec Tailwind v4, aligné avec les préférences techniques du PRD Cette approche offre : - Base solide et officielle avec Next.js 16 - Flexibilité pour intégrer shadcn/ui avec Tailwind v4 - Alignement avec les contraintes techniques du projet (Next.js 16 + Tailwind 4 + shadcn/ui) **Initialization Command:** ```bash # 1. Créer le projet Next.js 16 avec TypeScript, Tailwind, ESLint npx create-next-app@latest chartbastan --typescript --eslint --tailwind --app --src-dir --turbopack cd chartbastan # 2. Initialiser shadcn/ui avec Tailwind v4 (canary pour v4) npx shadcn@canary init ``` **Architectural Decisions Provided by Starter:** **Language & Runtime:** - TypeScript avec configuration stricte activée - Node.js 20.9+ requis (minimum pour Next.js 16) - App Router (Next.js 16) par défaut avec Server Components **Styling Solution:** - Tailwind CSS v4 configuré via shadcn CLI - shadcn/ui avec style "new-york" par défaut - CSS Variables pour theming (dark mode support) - Configuration via `components.json` **Build Tooling:** - Turbopack activé par défaut (bundler rapide de Next.js) - Optimisations automatiques (Server Components, code splitting par route) - Alias `@/*` configuré pour imports simplifiés **Code Organization:** - Structure `src/` directory pour séparation claire - App Router avec `/app` directory pour routing - Composants UI dans `components/ui/` (copiés localement) - Utilitaires dans `lib/utils.ts` (helper `cn()` pour classnames) **Development Experience:** - Hot reloading avec Turbopack pour développement rapide - ESLint configuré avec règles Next.js - TypeScript strict mode pour sécurité de types - Support Server Components par défaut (réduction bundle client) **Note:** L'initialisation du projet avec cette commande devrait être la première story d'implémentation. ## Core Architectural Decisions ### Decision Priority Analysis **Critical Decisions (Block Implementation):** - Architecture des données (ORM, migrations) - Authentification et autorisation - Patterns API et communication - Gestion d'état frontend - Infrastructure de déploiement **Important Decisions (Shape Architecture):** - Stratégie de cache - Monitoring et logging - Gestion d'erreurs standardisée - Rate limiting **Deferred Decisions (Post-MVP):** - Migration SQLite → PostgreSQL/MySQL (Phase 2+) - Optimisations avancées de performance - Multi-région deployment - CDN et edge caching ### Data Architecture **ORM Selection:** **FastAPI Backend:** - **Choice:** SQLAlchemy 2.0.45 (latest stable) - **Rationale:** - Mature, bien intégré avec FastAPI - Support async natif pour performance - Compatible avec Pydantic pour validation - Migration facile vers PostgreSQL/MySQL en Phase 2 - **Migration Tool:** Alembic pour migrations de schéma - **Affects:** Service FastAPI (analytics, ML, sentiment analysis) **Next.js API Routes:** - **Choice:** Drizzle ORM v0.44.7 (stable) avec `better-sqlite3` - **Rationale:** - TypeScript-first, excellent DX - Léger et performant - Support SQLite natif avec `better-sqlite3` - Migrations via Drizzle Kit - Compatible avec Server Components Next.js - **Migration Tool:** Drizzle Kit pour migrations - **Affects:** Next.js API routes (authentification, API légère) **Data Modeling Approach:** - **Schema Design:** Modélisation relationnelle classique avec normalisation - **Validation:** - FastAPI: Pydantic models pour validation des entrées/sorties - Next.js: Zod pour validation côté API routes (cohérence TypeScript) - **Migration Strategy:** - Migrations versionnées (Alembic + Drizzle Kit) - Scripts de migration pour Phase 1 → Phase 2 (SQLite → PostgreSQL) **Caching Strategy:** - **Phase 1:** Pas de cache distribué (SQLite suffisant) - **Phase 2+:** Redis pour cache de prédictions et données fréquemment accédées - **Frontend:** React Query (TanStack Query) pour cache côté client avec invalidation intelligente ### Authentication & Security **Authentication Method:** - **Choice:** Better Auth v1.4.4 (compatible Next.js 16) - **Rationale:** - Compatible officiellement avec Next.js 16 (contrairement à NextAuth.js v4) - Support stateless auth (JWT) - Migration path depuis NextAuth.js documentée - Support OAuth (Google, Twitter) pour Phase 2 - **Version:** v1.4.4 (production-ready) - **Affects:** Next.js API routes, système d'authentification **Authorization Patterns:** - **Role-Based Access Control (RBAC):** Gratuit vs Premium - **Permissions:** - Gratuit: 1-2 prédictions/jour, accès limité - Premium: Accès illimité, métriques avancées, API prioritaire - **Implementation:** Middleware Next.js pour protection des routes API **Security Middleware:** - **FastAPI:** - CORS configuré pour domaines autorisés - Rate limiting via `slowapi` ou middleware custom - Validation Pydantic pour toutes les entrées - **Next.js:** - CSRF protection via middleware - Secure cookies (HttpOnly, Secure, SameSite) - Headers de sécurité (CSP, X-Frame-Options, etc.) **Data Encryption:** - **At Rest:** SQLite avec chiffrement optionnel (Phase 2+) - **In Transit:** HTTPS obligatoire (TLS 1.3) - **Secrets:** Variables d'environnement, jamais en code - **Passwords:** Hashing avec bcrypt (via Better Auth) ### API & Communication Patterns **API Design Pattern:** - **Choice:** RESTful API avec OpenAPI 3.1 - **Rationale:** - Standard, bien compris - Documentation automatique avec FastAPI - Compatible avec génération de clients TypeScript - **Version:** OpenAPI 3.1 (supporté nativement par FastAPI 0.128.0+) **API Documentation:** - **FastAPI:** - Swagger UI intégré (`/docs`) - Redoc alternatif (`/redoc`) - OpenAPI schema exportable (`/openapi.json`) - Pydantic models pour schémas automatiques - **Best Practices:** - Docstrings Markdown pour chaque endpoint - Tags pour groupement logique - Exemples dans les schémas - Documentation des erreurs (400, 401, 404, 500) - **Production:** Désactiver `/docs` et `/redoc` ou les protéger par authentification **Error Handling Standards:** - **Format Standardisé:** ```json { "error": { "code": "ERROR_CODE", "message": "Human-readable message", "details": {} } } ``` - **HTTP Status Codes:** - 200: Success - 400: Bad Request (validation) - 401: Unauthorized - 403: Forbidden (premium required) - 404: Not Found - 429: Too Many Requests (rate limit) - 500: Internal Server Error - **Logging:** Tous les erreurs 4xx/5xx loggés avec contexte **Rate Limiting Strategy:** - **FastAPI:** - `slowapi` ou middleware custom - Limites différenciées: Gratuit (10 req/min), Premium (100 req/min) - Headers `X-RateLimit-*` pour transparence - **Next.js API Routes:** - Rate limiting par utilisateur (Better Auth) - Protection contre abuse - **External APIs:** - Gestion proactive des limites Twitter (1000 req/heure) - Priorisation dynamique (matchs VIP) - Modes dégradés (Reddit + RSS si Twitter down) **Communication Between Services:** - **FastAPI ↔ Next.js:** - HTTP REST pour communication synchrone - RabbitMQ pour communication asynchrone (scraping, analyse) - **Message Queue:** RabbitMQ pour découplage scraping/analyse - **Service Discovery:** URLs configurées via variables d'environnement (Phase 1) ### Frontend Architecture **State Management:** - **Choice:** Zustand v5.0.9 + React Query (TanStack Query) - **Rationale:** - Zustand: Léger, pas de provider, SSR-safe avec `unstable_ssrSafe` - React Query: Cache intelligent, synchronisation serveur, invalidation automatique - Complémentaire: Zustand pour état UI local, React Query pour données serveur - **Version:** Zustand v5.0.9 (latest stable) - **Affects:** Composants React, gestion d'état global **Component Architecture:** - **Pattern:** Feature-based organization avec co-location - **Structure:** ``` src/ app/ # Routes (App Router) components/ ui/ # shadcn/ui components features/ # Feature-specific components predictions/ dashboard/ lib/ # Utilities, hooks stores/ # Zustand stores ``` - **Server Components:** Par défaut, `use client` uniquement si nécessaire **Routing Strategy:** - **Choice:** Next.js App Router (déjà décidé par starter) - **File-based routing** avec layouts et loading states - **Protected Routes:** Middleware pour authentification **Performance Optimization:** - **Code Splitting:** Automatique par route (App Router) - **Image Optimization:** Next.js Image component - **Bundle Analysis:** `@next/bundle-analyzer` pour monitoring - **Lazy Loading:** Dynamic imports pour composants lourds (D3.js) - **Server Components:** Maximiser pour réduire bundle client ### Infrastructure & Deployment **Hosting Strategy:** - **Frontend (Next.js):** - **Phase 1:** Vercel (gratuit, optimisé Next.js, déploiement automatique) - **Rationale:** Zero-config, excellent DX, CDN intégré - **Backend (FastAPI):** - **Phase 1:** Railway ou Render (budget 10-20€/mois) - **Rationale:** Support Python, déploiement simple, scaling facile - **Database:** - **Phase 1:** SQLite (fichier local, backup manuel) - **Phase 2+:** PostgreSQL sur Railway/Render ou Supabase **CI/CD Pipeline:** - **Choice:** GitHub Actions - **Workflow:** - Lint + Type check sur PR - Tests unitaires (si implémentés Phase 2+) - Build et déploiement automatique sur merge main - **Environments:** - `development`: Local - `staging`: Vercel Preview (auto) - `production`: Vercel Production + Railway/Render **Environment Configuration:** - **Management:** `.env.local` (dev), `.env.production` (prod) - **Secrets:** Variables d'environnement dans Vercel/Railway - **Validation:** Zod pour validation des env vars au runtime **Monitoring and Logging:** - **Phase 1:** - **Logging:** Console logs structurés (JSON) - **Errors:** Sentry (plan gratuit) pour tracking erreurs - **Uptime:** UptimeRobot (gratuit) pour monitoring basique - **Phase 2+:** - **APM:** Datadog ou New Relic (si budget) - **Analytics:** Vercel Analytics intégré - **Performance:** Web Vitals monitoring **Scaling Strategy:** - **Phase 1:** Vertical scaling (upgrade instance) - **Phase 2+:** - Horizontal scaling (multiple instances FastAPI) - Load balancer (Railway/Render) - Database: Migration PostgreSQL avec connection pooling - CDN: Vercel Edge Network (automatique) ### Decision Impact Analysis **Implementation Sequence:** 1. **Foundation:** - Initialiser Next.js 16 avec create-next-app - Configurer shadcn/ui avec Tailwind v4 - Setup FastAPI avec SQLAlchemy - Configurer SQLite (FastAPI + Next.js) 2. **Core Services:** - Implémenter Better Auth (authentification) - Setup Drizzle ORM (Next.js) - Setup SQLAlchemy + Alembic (FastAPI) - Configurer RabbitMQ pour queue 3. **API Layer:** - Définir schémas OpenAPI (FastAPI) - Implémenter endpoints REST - Setup rate limiting - Documentation API 4. **Frontend:** - Configurer Zustand + React Query - Implémenter composants UI (shadcn) - Setup routing et protection - Intégration D3.js pour visualisations 5. **Infrastructure:** - Setup Vercel (frontend) - Setup Railway/Render (backend) - Configurer CI/CD (GitHub Actions) - Setup monitoring (Sentry, UptimeRobot) **Cross-Component Dependencies:** - **Authentication → API:** Better Auth protège toutes les routes API - **Database → Services:** SQLAlchemy (FastAPI) et Drizzle (Next.js) partagent le même SQLite (Phase 1) - **Queue → Scraping:** RabbitMQ découple scraping Twitter/Reddit de l'analyse - **Frontend → Backend:** React Query synchronise état avec API FastAPI - **Monitoring → All:** Sentry track erreurs dans tous les services ## Implementation Patterns & Consistency Rules ### Pattern Categories Defined **Critical Conflict Points Identified:** 15+ zones où les agents AI pourraient faire des choix différents, nécessitant des patterns stricts pour garantir la cohérence. ### Naming Patterns **Database Naming Conventions:** **FastAPI (SQLAlchemy):** - **Tables:** `snake_case`, pluriel : `users`, `predictions`, `matches`, `energy_scores` - **Columns:** `snake_case` : `user_id`, `created_at`, `is_premium`, `energy_score` - **Foreign Keys:** `{table}_id` : `user_id`, `match_id`, `prediction_id` - **Indexes:** `idx_{table}_{column}` : `idx_users_email`, `idx_predictions_match_id` - **Constraints:** `{table}_{column}_{constraint}` : `users_email_unique`, `predictions_user_id_fk` **Next.js (Drizzle ORM):** - **Tables:** Même convention que SQLAlchemy (`snake_case`, pluriel) - **Schema Definition:** Utiliser `snake_case` dans les schémas Drizzle pour correspondre à SQLite - **TypeScript Types:** Générer types TypeScript avec `snake_case` → `camelCase` via Drizzle **Rationale:** Cohérence entre les deux ORMs partageant la même base SQLite. SQLAlchemy utilise traditionnellement `snake_case`, donc Drizzle doit suivre. **API Naming Conventions:** **REST Endpoints:** - **Base URLs:** Pluriel, `snake_case` : `/api/v1/users`, `/api/v1/predictions`, `/api/v1/matches` - **Route Parameters:** `{id}` format : `/api/v1/users/{id}`, `/api/v1/matches/{match_id}` - **Query Parameters:** `snake_case` : `?user_id=123&limit=10&offset=0` - **Nested Resources:** `/api/v1/users/{user_id}/predictions` - **Actions:** `/api/v1/predictions/{id}/validate`, `/api/v1/matches/{id}/analyze` **Headers:** - **Custom Headers:** `X-` prefix : `X-API-Key`, `X-User-Id`, `X-RateLimit-Remaining` - **Standard Headers:** Respecter conventions HTTP standard **Code Naming Conventions:** **Python (FastAPI):** - **Files:** `snake_case.py` : `user_service.py`, `prediction_service.py`, `energy_calculator.py` - **Classes:** `PascalCase` : `UserService`, `PredictionService`, `EnergyCalculator` - **Functions:** `snake_case` : `get_user_by_id()`, `calculate_energy_score()`, `create_prediction()` - **Variables:** `snake_case` : `user_id`, `energy_score`, `is_premium` - **Constants:** `UPPER_SNAKE_CASE` : `MAX_PREDICTIONS_FREE`, `API_RATE_LIMIT` **TypeScript/JavaScript (Next.js):** - **Files:** `kebab-case.tsx` ou `PascalCase.tsx` pour composants : `user-card.tsx`, `UserCard.tsx`, `prediction-service.ts` - **Components:** `PascalCase` : `UserCard`, `PredictionDashboard`, `EnergyMeter` - **Functions:** `camelCase` : `getUserById()`, `calculateEnergyScore()`, `createPrediction()` - **Variables:** `camelCase` : `userId`, `energyScore`, `isPremium` - **Constants:** `UPPER_SNAKE_CASE` : `MAX_PREDICTIONS_FREE`, `API_RATE_LIMIT` - **Types/Interfaces:** `PascalCase` : `User`, `Prediction`, `EnergyScore` **Hooks:** `camelCase` avec préfixe `use` : `useUser()`, `usePredictions()`, `useEnergyScore()` ### Structure Patterns **Project Organization:** **FastAPI Backend Structure:** ``` backend/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI app entry │ ├── config.py # Configuration │ ├── database.py # SQLAlchemy setup │ ├── models/ # SQLAlchemy models │ │ ├── __init__.py │ │ ├── user.py │ │ ├── prediction.py │ │ └── match.py │ ├── schemas/ # Pydantic schemas │ │ ├── __init__.py │ │ ├── user.py │ │ └── prediction.py │ ├── api/ # API routes │ │ ├── __init__.py │ │ ├── v1/ │ │ │ ├── __init__.py │ │ │ ├── users.py │ │ │ └── predictions.py │ ├── services/ # Business logic │ │ ├── __init__.py │ │ ├── user_service.py │ │ ├── prediction_service.py │ │ └── energy_calculator.py │ ├── repositories/ # Data access layer │ │ ├── __init__.py │ │ ├── user_repository.py │ │ └── prediction_repository.py │ └── utils/ # Utilities │ ├── __init__.py │ ├── logger.py │ └── validators.py ├── alembic/ # Migrations │ ├── versions/ │ └── env.py ├── tests/ # Tests (co-located or separate) │ ├── __init__.py │ ├── test_users.py │ └── test_predictions.py ├── requirements.txt └── .env ``` **Next.js Frontend Structure:** ``` frontend/ ├── src/ │ ├── app/ # App Router routes │ │ ├── layout.tsx │ │ ├── page.tsx │ │ ├── (auth)/ │ │ │ ├── login/ │ │ │ └── register/ │ │ ├── dashboard/ │ │ │ └── page.tsx │ │ └── api/ # Next.js API routes │ │ └── v1/ │ │ ├── users/ │ │ └── predictions/ │ ├── components/ │ │ ├── ui/ # shadcn/ui components │ │ │ ├── button.tsx │ │ │ └── card.tsx │ │ └── features/ # Feature components │ │ ├── predictions/ │ │ │ ├── PredictionCard.tsx │ │ │ └── PredictionList.tsx │ │ └── dashboard/ │ │ └── Dashboard.tsx │ ├── lib/ │ │ ├── utils.ts # Utilities (cn helper, etc.) │ │ ├── api.ts # API client │ │ └── validations.ts # Zod schemas │ ├── stores/ # Zustand stores │ │ ├── user-store.ts │ │ └── prediction-store.ts │ ├── hooks/ # Custom React hooks │ │ ├── use-user.ts │ │ └── use-predictions.ts │ └── types/ # TypeScript types │ ├── user.ts │ └── prediction.ts ├── public/ # Static assets ├── drizzle/ # Drizzle migrations │ └── migrations/ ├── tests/ # Tests (co-located or separate) │ └── components/ └── .env.local ``` **File Structure Patterns:** - **Tests:** Co-locés avec les fichiers (`*.test.ts`, `test_*.py`) OU dans dossier `tests/` séparé - **Config Files:** `.env`, `.env.local`, `config.py`, `next.config.js` à la racine - **Static Assets:** `public/` pour Next.js, `static/` pour FastAPI - **Documentation:** `docs/` à la racine du projet ### Format Patterns **API Response Formats:** **Success Response:** ```json { "data": { "id": 1, "user_id": 123, "energy_score": 0.75, "created_at": "2026-01-15T10:30:00Z" }, "meta": { "timestamp": "2026-01-15T10:30:00Z", "version": "v1" } } ``` **Error Response:** ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid user_id provided", "details": { "field": "user_id", "reason": "Must be a positive integer" } }, "meta": { "timestamp": "2026-01-15T10:30:00Z", "request_id": "req_abc123" } } ``` **List Response:** ```json { "data": [ {"id": 1, "user_id": 123}, {"id": 2, "user_id": 456} ], "meta": { "total": 2, "page": 1, "per_page": 10, "timestamp": "2026-01-15T10:30:00Z" } } ``` **Data Exchange Formats:** - **JSON Field Naming:** `snake_case` dans les réponses API (cohérence avec database) - **Date Format:** ISO 8601 strings : `"2026-01-15T10:30:00Z"` (UTC) - **Boolean:** `true`/`false` (pas de 1/0) - **Null:** `null` (pas de `undefined` en JSON) - **Arrays:** Toujours des arrays, jamais d'objets pour listes **Type Conversions:** - **Frontend:** Convertir `snake_case` API → `camelCase` TypeScript via transformation layer - **Backend:** Accepter `camelCase` dans les requêtes, convertir en `snake_case` pour DB ### Communication Patterns **Event System Patterns (RabbitMQ):** **Event Naming:** - Format: `{entity}.{action}` : `user.created`, `prediction.updated`, `match.analyzed` - Lowercase avec points comme séparateurs - Actions: `created`, `updated`, `deleted`, `analyzed`, `scraped` **Event Payload Structure:** ```json { "event": "prediction.created", "version": "1.0", "timestamp": "2026-01-15T10:30:00Z", "data": { "prediction_id": 123, "user_id": 456, "match_id": 789 }, "metadata": { "source": "api", "user_id": 456 } } ``` **State Management Patterns:** **Zustand Store Structure:** ```typescript interface UserState { user: User | null; isLoading: boolean; error: string | null; setUser: (user: User) => void; clearUser: () => void; } const useUserStore = create((set) => ({ user: null, isLoading: false, error: null, setUser: (user) => set({ user, error: null }), clearUser: () => set({ user: null, error: null }), })); ``` **React Query Patterns:** - **Query Keys:** Array format : `['users', userId]`, `['predictions', { matchId }]` - **Mutations:** Utiliser `useMutation` avec `onSuccess`/`onError` - **Cache Invalidation:** `queryClient.invalidateQueries(['predictions'])` **State Update Rules:** - **Immutable Updates:** Toujours créer de nouveaux objets/arrays - **Action Naming:** `set{Entity}`, `update{Entity}`, `clear{Entity}`, `fetch{Entity}` ### Process Patterns **Error Handling Patterns:** **FastAPI:** ```python from fastapi import HTTPException # Standard error raising raise HTTPException( status_code=400, detail={ "code": "VALIDATION_ERROR", "message": "Invalid input", "details": {"field": "user_id"} } ) ``` **Next.js:** ```typescript // API Routes if (!user) { return NextResponse.json( { error: { code: "NOT_FOUND", message: "User not found", }, }, { status: 404 } ); } // Components try { const data = await fetchUser(); } catch (error) { // Log to Sentry console.error("Failed to fetch user:", error); // Show user-friendly message setError("Unable to load user. Please try again."); } ``` **Error Boundary:** - Utiliser React Error Boundaries pour erreurs de rendu - Logger toutes les erreurs à Sentry avec contexte **Loading State Patterns:** **Naming:** - `isLoading` pour état de chargement principal - `isFetching` pour refetch en arrière-plan (React Query) - `isSubmitting` pour formulaires **Implementation:** ```typescript // Zustand const useStore = create((set) => ({ isLoading: false, setLoading: (loading) => set({ isLoading: loading }), })); // React Query const { data, isLoading, isFetching } = useQuery(['users'], fetchUsers); ``` **Loading UI:** - Skeleton loaders pour contenu principal - Spinners pour actions rapides - Désactiver les boutons pendant `isSubmitting` ### Enforcement Guidelines **All AI Agents MUST:** 1. **Respecter les conventions de nommage:** - Python: `snake_case` pour fichiers, fonctions, variables - TypeScript: `camelCase` pour fonctions/variables, `PascalCase` pour composants/types - Database: `snake_case` pour tables/colonnes (cohérence entre SQLAlchemy et Drizzle) 2. **Suivre la structure de projet définie:** - Ne pas créer de fichiers en dehors des dossiers définis - Co-locater les tests avec les fichiers OU utiliser `tests/` - Respecter la séparation `services/`, `repositories/`, `api/` 3. **Utiliser les formats API standardisés:** - Toujours wrapper les réponses dans `{data, meta}` ou `{error, meta}` - Utiliser les codes d'erreur définis - Dates en ISO 8601 UTC 4. **Implémenter la gestion d'erreurs cohérente:** - Logger toutes les erreurs avec contexte - Retourner des messages utilisateur-friendly - Utiliser les patterns d'erreur définis 5. **Respecter les patterns de state management:** - Zustand pour état UI local - React Query pour données serveur - Immutable updates uniquement **Pattern Enforcement:** - **Code Review:** Vérifier la conformité aux patterns dans chaque PR - **Linting:** Configurer ESLint (Next.js) et flake8/black (Python) avec règles strictes - **Type Safety:** TypeScript strict mode + Pydantic pour validation - **Documentation:** Documenter toute exception aux patterns avec justification **Process for Updating Patterns:** 1. Identifier le besoin de changement 2. Discuter l'impact sur l'existant 3. Mettre à jour ce document d'architecture 4. Communiquer le changement à l'équipe 5. Migrer le code existant si nécessaire ### Pattern Examples **Good Examples:** **Database Model (SQLAlchemy):** ```python class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) email = Column(String, unique=True, index=True, nullable=False) is_premium = Column(Boolean, default=False) created_at = Column(DateTime, default=datetime.utcnow) ``` **API Endpoint (FastAPI):** ```python @router.get("/api/v1/users/{user_id}", response_model=UserResponse) async def get_user(user_id: int): user = await user_service.get_by_id(user_id) if not user: raise HTTPException(status_code=404, detail="User not found") return {"data": user, "meta": {"timestamp": datetime.utcnow().isoformat()}} ``` **React Component:** ```typescript export function UserCard({ userId }: { userId: number }) { const { data: user, isLoading, error } = useQuery( ['users', userId], () => fetchUser(userId) ); if (isLoading) return ; if (error) return ; return {user.name}; } ``` **Anti-Patterns:** ❌ **Mixing Naming Conventions:** ```python # BAD class userService: # Should be UserService def getUserData(self): # Should be get_user_data userId = 123 # Should be user_id ``` ❌ **Inconsistent API Responses:** ```json // BAD - Direct response {"id": 1, "name": "John"} // GOOD - Wrapped response {"data": {"id": 1, "name": "John"}, "meta": {...}} ``` ❌ **Mutable State Updates:** ```typescript // BAD state.users.push(newUser); // GOOD setUsers([...users, newUser]); ``` ❌ **Inconsistent Error Handling:** ```python # BAD - Different error formats raise ValueError("Error") return {"error": "Error"} raise HTTPException(status_code=500) # GOOD - Consistent format raise HTTPException( status_code=400, detail={"code": "ERROR_CODE", "message": "Error"} ) ```