Skip to content

ffcam-aura/ffcam-formations

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

107 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

FFCAM Formations

Keyway Secrets Vercel Deploy License

Application web pour afficher et filtrer les formations du FFCAM (FΓ©dΓ©ration FranΓ§aise des Clubs Alpins et de Montagne). Cet outil a Γ©tΓ© construit par des dΓ©veloppeurs bΓ©nΓ©voles du ComitΓ© RΓ©gional Auvergne Rhone-Alpes.

Production : https://formations.ffcam-aura.fr

FonctionnalitΓ©s

  • Affichage des formations : Visualisez les formations avec les dΓ©tails (lieu, discipline, tarifs, dates, places disponibles)
  • Filtrage avancΓ© : Filtrez par lieu, discipline, dates et disponibilitΓ©s
  • Notifications par email : Recevez des alertes pour les nouvelles formations de vos disciplines favorites
  • Protection des emails : Les adresses email des contacts sont masquΓ©es (anti-scraping)
  • Synchronisation automatique : Mise Γ  jour quotidienne des formations depuis le site FFCAM

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
│                              SOURCES DE DONNÉES                              │
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                       β”‚
β”‚    β”‚   Site FFCAM     β”‚         β”‚      Clerk       β”‚                       β”‚
β”‚    β”‚ (formations.html)β”‚         β”‚ (Authentification)β”‚                       β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β”‚
β”‚             β”‚                            β”‚                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                            β”‚
              β–Ό                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              NEXT.JS APPLICATION                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                         CRON JOBS (Vercel)                          β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
β”‚  β”‚  β”‚ /api/sync (4h UTC)  β”‚    β”‚ /api/notifications/send (6h UTC)β”‚   β”‚   β”‚
β”‚  β”‚  β”‚                     β”‚    β”‚                                  β”‚   β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Scrape FFCAM     β”‚    β”‚  β€’ Trouve nouvelles formations  β”‚   β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Parse HTML       β”‚    β”‚  β€’ Match prΓ©fΓ©rences users      β”‚   β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Upsert DB        β”‚    β”‚  β€’ Envoie emails                β”‚   β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Ping healthcheck β”‚    β”‚  β€’ Ping healthcheck email       β”‚   β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                            API ROUTES                                β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
β”‚  β”‚  β”‚ GET /formations  β”‚  β”‚ GET/POST /usersβ”‚  β”‚ GET /sync/last     β”‚   β”‚   β”‚
β”‚  β”‚  β”‚ (rate limited)   β”‚  β”‚ (auth Clerk)   β”‚  β”‚                    β”‚   β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                          SERVICES                                    β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚
β”‚  β”‚  β”‚ SyncService    β”‚ β”‚ FormationServiceβ”‚ β”‚ NotificationService    β”‚  β”‚   β”‚
β”‚  β”‚  β”‚ β€’ synchronize  β”‚ β”‚ β€’ upsert        β”‚ β”‚ β€’ notifyBatchFormationsβ”‚  β”‚   β”‚
β”‚  β”‚  β”‚ β€’ pingHealth   β”‚ β”‚ β€’ getRecent     β”‚ β”‚ β€’ matchPreferences     β”‚  β”‚   β”‚
β”‚  β”‚  β”‚ β€’ sendReport   β”‚ β”‚ β€’ getAll        β”‚ β”‚                        β”‚  β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                              β”‚   β”‚
β”‚  β”‚  β”‚ EmailService   β”‚ β”‚ UserService     β”‚                              β”‚   β”‚
β”‚  β”‚  β”‚ β€’ sendEmail    β”‚ β”‚ β€’ getPreferencesβ”‚                              β”‚   β”‚
β”‚  β”‚  β”‚ (via SMTP)     β”‚ β”‚ β€’ updatePrefs   β”‚                              β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                              β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                         REPOSITORIES                                 β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                     β”‚   β”‚
β”‚  β”‚  β”‚ FormationRepository  β”‚  β”‚ UserRepository   β”‚                     β”‚   β”‚
β”‚  β”‚  β”‚ β€’ upsertFormations   β”‚  β”‚ β€’ findPreferencesβ”‚                     β”‚   β”‚
β”‚  β”‚  β”‚ β€’ findAll            β”‚  β”‚ β€’ upsertPrefs    β”‚                     β”‚   β”‚
β”‚  β”‚  β”‚ β€’ findRecent         β”‚  β”‚ β€’ findUsersToNotifyβ”‚                   β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                     β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
                                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           INFRASTRUCTURE                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚   PostgreSQL     β”‚  β”‚     Brevo        β”‚  β”‚    Healthchecks.io     β”‚    β”‚
β”‚  β”‚   (Neon DB)      β”‚  β”‚   (SMTP Email)   β”‚  β”‚    (Monitoring)        β”‚    β”‚
β”‚  β”‚                  β”‚  β”‚                  β”‚  β”‚                        β”‚    β”‚
β”‚  β”‚ β€’ formations     β”‚  β”‚ β€’ Notifications  β”‚  β”‚ β€’ Ping sync status     β”‚    β”‚
β”‚  β”‚ β€’ disciplines    β”‚  β”‚ β€’ Error reports  β”‚  β”‚ β€’ Email delivery check β”‚    β”‚
β”‚  β”‚ β€’ user_prefs     β”‚  β”‚ β€’ Healthchecks   β”‚  β”‚ β€’ Dead man's switch    β”‚    β”‚
β”‚  β”‚ β€’ lieux          β”‚  β”‚                  β”‚  β”‚                        β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                β”‚
β”‚  β”‚     Sentry       β”‚  β”‚  Vercel Analytics β”‚                               β”‚
β”‚  β”‚   (Errors)       β”‚  β”‚   (Usage stats)   β”‚                               β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Technologies

CatΓ©gorie Technologies
Framework Next.js 15, React 19, TypeScript
Base de donnΓ©es PostgreSQL (Neon) + Prisma ORM
Authentification Clerk
UI Tailwind CSS, Radix UI
Email Nodemailer + Brevo SMTP
Monitoring Sentry, Healthchecks.io, Vercel Analytics
Secrets Keyway
Tests Vitest, React Testing Library, Playwright (e2e)

Monitoring & Alerting

L'application utilise plusieurs systèmes de monitoring :

Healthchecks.io (Dead Man's Switch)

  • Sync healthcheck : Ping quotidien aprΓ¨s synchronisation

    • βœ… SuccΓ¨s : formations synchronisΓ©es
    • ⚠️ Partiel : erreurs sur certaines formations β†’ email d'alerte
    • ❌ Γ‰chec : erreur critique β†’ email + ping /fail
  • Email healthcheck : Email quotidien pour vΓ©rifier la dΓ©livrabilitΓ©

    • EnvoyΓ© Γ  une adresse @hc-ping.com qui attend un email rΓ©gulier

Sentry

  • Capture automatique des erreurs frontend et backend
  • Monitoring des performances
  • Source maps pour debug en production

Alertes Email

Γ‰vΓ©nement Destinataire Contenu
Erreur critique sync Admin Stack trace + Γ©tat avant erreur
Erreurs partielles sync Admin Liste des formations en Γ©chec
Nouvelle formation Utilisateurs Formations matchant leurs prΓ©fΓ©rences

Variables d'Environnement

Les secrets de ce projet sont gΓ©rΓ©s via Keyway, qui synchronise automatiquement les variables d'environnement avec Vercel. Cela permet de :

  • Centraliser la gestion des secrets pour toute l'Γ©quipe
  • Versionner les changements de configuration
  • Γ‰viter de partager des .env par Slack ou email
# Base de donnΓ©es
POSTGRES_URL="postgresql://..."
POSTGRES_URL_NON_POOLING="postgresql://..."

# Authentification Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_..."
CLERK_SECRET_KEY="sk_..."

# Email (Brevo SMTP)
SMTP_HOST="smtp-relay.brevo.com"
SMTP_PORT="587"
SMTP_USER="..."
SMTP_PASSWORD="..."
EMAIL_FROM="noreply@xxxxx"
EMAIL_SENDER_NAME="FFCAM Formations"
SYNC_NOTIFICATION_EMAIL="admin@xxxxx"

# Sécurité CRON (minimum 32 caractères)
CRON_SECRET="your-very-long-secret-at-least-32-chars"

# Monitoring (optionnel)
HEALTHCHECK_SYNC_URL="https://hc-ping.com/your-uuid"
HEALTHCHECK_NOTIFICATIONS_EMAIL="your-uuid@hc-ping.com"

DΓ©veloppement

PrΓ©requis

  • Node.js 20+
  • pnpm
  • PostgreSQL (ou Docker)

Installation

# Cloner le projet
git clone git@github.com:ffcam-aura/ffcam-formations.git
cd ffcam-formations

# Installer les dΓ©pendances
pnpm install

# Configurer les variables d'environnement
cp .env.example .env.local
# Γ‰diter .env.local avec vos valeurs

# Lancer la base de donnΓ©es (optionnel, si Docker)
docker run --name ffcam-postgres \
  -e POSTGRES_DB=ffcam_formations \
  -e POSTGRES_USER=ffcam_user \
  -e POSTGRES_PASSWORD=ffcam_password \
  -p 5432:5432 \
  -d postgres:15-alpine

# Appliquer les migrations
pnpm prisma migrate dev

# Lancer le serveur de dΓ©veloppement
pnpm dev

Commandes utiles

pnpm dev           # Serveur de dΓ©veloppement
pnpm build         # Build production
pnpm test          # Tests unitaires
pnpm test:watch    # Tests en mode watch
pnpm test:coverage # Couverture de tests
pnpm lint          # Linting
pnpm prisma studio # Interface graphique DB

Tests e2e (Playwright)

Les tests e2e vΓ©rifient que les pages publiques chargent correctement. Ils ne sont pas exΓ©cutΓ©s en CI (trop lents) mais doivent Γͺtre lancΓ©s manuellement avant une release importante.

pnpm test:e2e         # Lancer les tests e2e (headless)
pnpm test:e2e:headed  # Lancer avec navigateur visible
pnpm test:e2e:ui      # Interface Playwright interactive

Note : Les tests e2e nΓ©cessitent que le serveur de dΓ©veloppement soit dΓ©marrΓ© (Playwright le lance automatiquement).

Hooks Git

Husky vΓ©rifie automatiquement avant chaque push :

  • pnpm lint - Linting
  • pnpm build - Build sans erreurs

API

Endpoints publics

Endpoint Description Rate Limit
GET /api/formations Liste des formations 60 req/min
GET /api/sync/last Date dernière sync -

Endpoints protΓ©gΓ©s (CRON)

# Synchronisation manuelle
curl -X GET "https://formations.ffcam-aura.fr/api/sync" \
  -H "Authorization: Bearer YOUR_CRON_SECRET"

# Envoi notifications
curl -X GET "https://formations.ffcam-aura.fr/api/notifications/send" \
  -H "Authorization: Bearer YOUR_CRON_SECRET"

Endpoints utilisateur (Auth Clerk)

Endpoint MΓ©thode Description
/api/users GET RΓ©cupΓ©rer prΓ©fΓ©rences
/api/users POST Mettre Γ  jour prΓ©fΓ©rences

Corps de la requΓͺte POST :

{
  "disciplines": ["Alpinisme", "Escalade"]
}

DΓ©ploiement

L'application est dΓ©ployΓ©e automatiquement sur Vercel Γ  chaque push sur main.

CRON Jobs (Vercel)

ConfigurΓ©s dans vercel.json :

Job Schedule Description
/api/sync 4h UTC Synchronisation FFCAM
/api/notifications/send 6h UTC Envoi notifications

Contribuer

  1. Forkez ce dΓ©pΓ΄t
  2. CrΓ©ez une branche (git checkout -b feature/amazing-feature)
  3. Committez vos modifications (git commit -m 'Add amazing feature')
  4. Poussez vers la branche (git push origin feature/amazing-feature)
  5. Ouvrez une Pull Request

License

Ce projet est sous licence MIT License.

About

πŸ”οΈ Trouvez facilement votre prochaine formation montagne FFCAM : recherche avancΓ©e, filtres et notifications pour toutes les formations en France

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages