D'où viennent les données
Toutes les prévisions sont fournies par Open-Meteo, qui agrège les sorties des modèles météo numériques globaux (ECMWF, GFS, ICON, Météo-France ARPEGE/AROME…) sans clé d'API. Deux endpoints sont interrogés :
- Forecast API — couverture nuageuse par altitude (basse, moyenne, haute), visibilité, humidité, pression au niveau de la mer, probabilité de précipitations, horaires de lever et coucher
- Air Quality API — épaisseur optique des aérosols, PM2.5, poussières désertiques (modèle CAMS / Copernicus). Optionnel : si l'appel échoue, le score est calculé sans bonus aérosols
Un seul appel par endpoint, batché pour les 5 villes. Réponse mise en cache 30 minutes via Vercel ISR puis revalidée automatiquement.
La formule du score
Pour chaque lever et chaque coucher à venir, le score (entier de 0 à 100) est le produit de huit facteurs multiplicatifs :
score = canvas × lowBlock × clarity × aerosol × precip × structure × front × terrain
Chaque facteur vit à peu près dans [0, 1.2]. Le résultat est écrêté à [0, 100].
1. Toile nuageuse · canvas
Les nuages moyens (3–8 km) et hauts (cirrus, >8 km) captent la lumière rasante et la diffusent — ce sont eux qui peignent le ciel. Trop peu de nuages = ciel plat ; trop = couverture uniforme sans relief.
hm = (cloud_mid × 1.0 + cloud_high × 0.7) / 100 canvas = max( 1 − |hm − 0.5| / 0.5 , 0.3 × (1 − hm) )
Courbe en cloche centrée sur 50 % de couverture combinée, avec un plancher 0.3 × (1 − hm) pour qu'un ciel parfaitement clair reste un pastel et ne tombe pas à zéro.
2. Blocage par les nuages bas · lowBlock
À l'horizon, le soleil rasant doit pouvoir éclairer par en dessous les nuages moyens et hauts. Un plafond bas bloque cette lumière avant qu'elle ne peigne le ciel.
lowBlock = 1 − (cloud_low / 100)^0.8
Multiplicatif : 100 % de nuages bas → lowBlock = 0 → score = 0 quoi qu'il arrive ailleurs. L'exposant 0.8 (sub-linéaire) fait que 5 % de bas ne pénalise quasiment pas, mais 50 % divise déjà le score par deux.
3. Clarté de l'air · clarity
Air sec et limpide = teintes vives. Brume, humidité forte = couleurs ternes.
vis = clamp( visibility / 24000 , 0 , 1 ) // 0 à 24 km hum = 1 − clamp( (humidity − 40) / 55 , 0 , 1 ) // 1 si ≤40 %, 0 si ≥95 % clarity = 0.7 + 0.3 × ( 0.5 × vis + 0.5 × hum )
Plage : [0.7, 1.0]. La clarté peut amplifier ou atténuer mais jamais annuler.
4. Aérosols · aerosol
Des aérosols modérés (sable saharien, fumée lointaine, brume sèche) intensifient les rouges par diffusion Rayleigh-Mie — c'est ce qui fait les couchers spectaculaires après un coup de vent du Sud. Trop d'aérosols (pollution dense) ternissent au contraire. La cloche a son sommet à AOD ≈ 0.12.
si AOD ≤ 0.12 : aerosol = 0.94 + (1.16 − 0.94) × (AOD / 0.12) sinon : aerosol = max( 0.62 , 1.16 − (1.16 − 0.62) × (AOD − 0.12) / 0.68 )
Plage : [0.62, 1.16]. Source : modèle CAMS / Copernicus via Open-Meteo Air Quality.
5. Précipitations · precip
Pluie en cours = ciel chargé. Pénalité non-linéaire selon la probabilité de précipitations à l'heure de l'événement.
precip = 1 − 0.55 × (probabilité_pluie / 100)^1.2
À 50 % de probabilité → 0.76. À 100 % → 0.45.
6. Structure nuageuse · structure
Distinction qualitative entre cirrus (haut + air sec = texturé et lumineux, comme un voile peint) et stratus (mid + air humide = plat et uniforme).
si cloud_high > 30 % et humidité < 60 % :
bonus += 0.10 × ((cloud_high − 30) / 40)
si cloud_mid > 60 % et humidité > 75 % :
pénalité += 0.10 × ((cloud_mid − 60) / 30)
structure = 1 + bonus − pénalitéPlage approximative : [0.90, 1.10].
7. Passage de front · front
Une pression qui remonte fortement après une dépression annonce souvent un ciel spectaculaire : résidus de nuages, lumière qui revient. Calculé comme la différence de pression au sol entre l'événement et 24 h avant.
si Δp (24 h) ≤ 3 hPa : front = 1.0 sinon : front = min( 1.08 , 1 + (Δp − 3) / 60 )
Plage : [1.0, 1.08]. Effet modeste, conçu comme un bonus.
8. Bonus géographique · terrain
Multiplicateur statique par lieu reflétant la ligne d'horizon — à météo strictement égale, un site bien dégagé voit beaucoup plus de ciel qu'un site enclavé.
| Lieu | Facteur | Note |
|---|---|---|
| Coudoux | 1.02 | Plateau provençal, horizon dégagé vers l'ouest et l'est. |
| Corbières-en-Provence | 1.05 | Colline provençale, large ouverture sur les couchers. |
| Jonquerettes | 1.02 | Plaine du Comtat Venaissin, vue dégagée sur 360°. |
| Sare | 1.06 | Au pied de la Rhune, vue vers l'Atlantique au coucher. |
| Paris | 0.97 | Tissu urbain dense, horizon souvent obstrué par les bâtiments. |
| Bordeaux | 0.99 | Plaine girondine, fleuve large s'ouvrant vers l'estuaire. |
| Lyon | 1.00 | Au confluent du Rhône et de la Saône, colline de Fourvière à l'ouest. |
| Marseille | 1.04 | Façade méditerranéenne, collines et large horizon marin à l'ouest. |
| Nice | 1.05 | Côte d'Azur, baie des Anges grande ouverte vers le large. |
| Rennes | 0.98 | Plaine bretonne, ouvertures vers l'ouest atlantique. |
| Strasbourg | 0.99 | Plaine d'Alsace, large vue sur les Vosges au couchant. |
| Tokyo | 0.97 | Mégapole côtière, baie de Tokyo à l'est, mont Fuji à l'ouest par temps clair. |
Lissage temporel
Un golden hour dure environ 30 minutes, pas une seconde. Pour éviter qu'un voile bas passager fasse osciller violemment le score, les variables météo sont moyennées sur ±1 h autour de l'événement (T−1, T, T+1) avant d'entrer dans la formule.
Effet pratique : un score qui changeait toutes les demi-heures parce qu'un nuage passait à T+30 reste désormais stable si la situation globale autour de l'heure dorée est similaire.
Incertitude affichée
On calcule en plus le score à chaque heure dans une fenêtre ±2 h (T−2 à T+2), puis l'écart-type de ces cinq scores. Plus la météo change vite autour de l'événement, plus l'incertitude est élevée — et c'est ce ± qui s'affiche à côté du score.
Un score « Beau 64 ± 12 » assume que la prévision pourrait basculer entre Correct et Superbe selon le timing exact d'un voile nuageux. Un score « Superbe 78 ± 2 » est en revanche très fiable.
Niveaux de qualité
Seuils ajustés sur la distribution attendue des scores réels. Les couleurs reprennent celles du dégradé de fond.
| Score | Libellé | Teinte |
|---|---|---|
0–17 | Médiocre | #9aa0b5 |
18–34 | Quelconque | #c7a98f |
35–51 | Correct | #e3a85f |
52–67 | Beau | #f08a4b |
68–81 | Superbe | #ef5d56 |
82–100 | Exceptionnel | #e23e6b |
Le fond d'écran reflète le tier du meilleur des deux prochains événements (lever ou coucher), pour que la ville s'illumine dès qu'un beau ciel arrive — pas seulement le prochain créneau.
Limites et marges de progression
- Les nuages bas sont la variable la plus mal prédite à 3–4 jours, et c'est aussi celle qui peut faire passer un Superbe à Médiocre. L'incertitude se réduit beaucoup à H−12.
- Pas de calibration empirique : tous les coefficients sont des choix heuristiques. Un jeu d'observations réelles (photos + notes) permettrait d'ajuster les poids par régression.
- Pas d'imagerie satellite temps-réel. Utile seulement pour la dernière heure avant l'événement — peu pertinent pour planifier à plusieurs jours.
- L'humidité est mesurée à 2 m seulement. L'humidité en altitude serait plus pertinente pour distinguer cirrus et stratus, mais Open-Meteo ne l' expose pas directement dans la Forecast API.
- Le vent à l'horizon (vers où poussent les nuages) pourrait affiner la prédiction — variable présente dans Open-Meteo, à intégrer dans une prochaine version.
Code source
Le score est entièrement déterministe et tient dans lib/sunsetScore.ts. Tous les seuils, exposants et coefficients y sont centralisés pour faciliter le réglage — un changement, un rechargement, et les 40 prochains événements sont re-notés.