2026-02-01 09:31:38 +01:00

32 KiB
Raw Blame History

stepsCompleted inputDocuments workflowType project_name user_name date lastStep status completedAt
step-01-init
step-02-context
step-03-starter
step-04-decisions
step-05-patterns
step-06-structure
prd.md
architecture chartbastan Ramez 2026-01-15T21:00:00.000Z 8 complete 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:

# 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é:
{
  "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_casecamelCase 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:

{
  "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:

{
  "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:

{
  "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:

{
  "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:

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:

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:

// 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:

// 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):

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):

@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:

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:

# BAD
class userService:  # Should be UserService
    def getUserData(self):  # Should be get_user_data
        userId = 123  # Should be user_id

Inconsistent API Responses:

// BAD - Direct response
{"id": 1, "name": "John"}

// GOOD - Wrapped response
{"data": {"id": 1, "name": "John"}, "meta": {...}}

Mutable State Updates:

// BAD
state.users.push(newUser);

// GOOD
setUsers([...users, newUser]);

Inconsistent Error Handling:

# 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"}
)