---
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<UserState>((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 <UserCardSkeleton />;
  if (error) return <ErrorMessage error={error} />;
  
  return <Card>{user.name}</Card>;
}
```

**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"}
)
```
