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
- 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
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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) β β
β ββββββββββββββββββββ ββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| 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 |
| Nodemailer + Brevo SMTP | |
| Monitoring | Sentry, Healthchecks.io, Vercel Analytics |
| Secrets | Keyway |
| Tests | Vitest, React Testing Library, Playwright (e2e) |
L'application utilise plusieurs systèmes de monitoring :
-
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.comqui attend un email rΓ©gulier
- EnvoyΓ© Γ une adresse
- Capture automatique des erreurs frontend et backend
- Monitoring des performances
- Source maps pour debug en production
| Γ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 |
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
.envpar 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"- Node.js 20+
- pnpm
- PostgreSQL (ou Docker)
# 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 devpnpm 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 DBLes 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 interactiveNote : Les tests e2e nΓ©cessitent que le serveur de dΓ©veloppement soit dΓ©marrΓ© (Playwright le lance automatiquement).
Husky vΓ©rifie automatiquement avant chaque push :
pnpm lint- Lintingpnpm build- Build sans erreurs
| Endpoint | Description | Rate Limit |
|---|---|---|
GET /api/formations |
Liste des formations | 60 req/min |
GET /api/sync/last |
Date dernière sync | - |
# 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"| 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"]
}L'application est dΓ©ployΓ©e automatiquement sur Vercel Γ chaque push sur main.
ConfigurΓ©s dans vercel.json :
| Job | Schedule | Description |
|---|---|---|
/api/sync |
4h UTC | Synchronisation FFCAM |
/api/notifications/send |
6h UTC | Envoi notifications |
- Forkez ce dΓ©pΓ΄t
- CrΓ©ez une branche (
git checkout -b feature/amazing-feature) - Committez vos modifications (
git commit -m 'Add amazing feature') - Poussez vers la branche (
git push origin feature/amazing-feature) - Ouvrez une Pull Request
Ce projet est sous licence MIT License.