32 KiB
| stepsCompleted | inputDocuments | workflowType | project_name | user_name | date | lastStep | status | completedAt | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
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 :
create-next-apppour établir la base Next.js 16 avec toutes les configurations essentiellesshadcn@canarypour 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
/appdirectory pour routing - Composants UI dans
components/ui/(copiés localement) - Utilitaires dans
lib/utils.ts(helpercn()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
slowapiou 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
- Swagger UI intégré (
- 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
/docset/redocou 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:
slowapiou 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
- Zustand: Léger, pas de provider, SSR-safe avec
- 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 clientuniquement 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-analyzerpour 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: Localstaging: 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:
-
Foundation:
- Initialiser Next.js 16 avec create-next-app
- Configurer shadcn/ui avec Tailwind v4
- Setup FastAPI avec SQLAlchemy
- Configurer SQLite (FastAPI + Next.js)
-
Core Services:
- Implémenter Better Auth (authentification)
- Setup Drizzle ORM (Next.js)
- Setup SQLAlchemy + Alembic (FastAPI)
- Configurer RabbitMQ pour queue
-
API Layer:
- Définir schémas OpenAPI (FastAPI)
- Implémenter endpoints REST
- Setup rate limiting
- Documentation API
-
Frontend:
- Configurer Zustand + React Query
- Implémenter composants UI (shadcn)
- Setup routing et protection
- Intégration D3.js pour visualisations
-
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_casedans les schémas Drizzle pour correspondre à SQLite - TypeScript Types: Générer types TypeScript avec
snake_case→camelCasevia 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.tsxouPascalCase.tsxpour 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 dossiertests/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_casedans 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 deundefineden JSON) - Arrays: Toujours des arrays, jamais d'objets pour listes
Type Conversions:
- Frontend: Convertir
snake_caseAPI →camelCaseTypeScript via transformation layer - Backend: Accepter
camelCasedans les requêtes, convertir ensnake_casepour 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
useMutationaveconSuccess/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:
isLoadingpour état de chargement principalisFetchingpour refetch en arrière-plan (React Query)isSubmittingpour 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:
-
Respecter les conventions de nommage:
- Python:
snake_casepour fichiers, fonctions, variables - TypeScript:
camelCasepour fonctions/variables,PascalCasepour composants/types - Database:
snake_casepour tables/colonnes (cohérence entre SQLAlchemy et Drizzle)
- Python:
-
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/
-
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
- Toujours wrapper les réponses dans
-
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
-
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:
- Identifier le besoin de changement
- Discuter l'impact sur l'existant
- Mettre à jour ce document d'architecture
- Communiquer le changement à l'équipe
- 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"}
)