Methodology

Every formula, every threshold, every data source. No black boxes.

Last reviewed: April 2026

Core principles

Honest scoring

Weather codes act as absolute blocks. A rainy day cannot score "excellent" no matter how mild the temperature is.

Capped penalties

Total activity penalty is capped at 60 points. No single bad variable can collapse the score to zero.

Reliability-aware

"Most Stable," "Sunniest," and "Least Windy" only consider days 1–7. Confidence drops 5% per day after that.

Deterministic

Same inputs always produce the same score. No machine learning, no per-user tuning, no hidden weights.

Data sources

Weather forecasts

Open-Meteo — aggregates ECMWF, GFS, ICON, and regional models. Updated hourly. We pull 14-day daily and 48-hour hourly forecasts.

Variables used: temperature_2m_max/min, precipitation_sum, precipitation_probability_max, wind_speed_10m_max, wind_gusts_10m_max, weather_code (WMO), uv_index_max.

Sunrise, sunset, golden hour, blue hour

On-site solar geometry (NOAA equations) computed from the location's coordinates, cross-checked against Open-Meteo's daily sunrise and sunset. All times are calculated and displayed in the target location's local timezone, not the browser's timezone.

Moon phase & illumination

Calculated client-side using astronomical algorithms (synodic month = 29.530589 days). Illumination percentage is globally consistent on a given UTC date — moon visibility timing differs by location.

Geocoding & location data

Nominatim (OpenStreetMap) for free-text search. Curated city dataset for ~412 destinations with editorial weather profiles.

Sub-score formulas

Each sub-score is normalized to 0–100 before being combined. These are the exact thresholds running in production.

Temperature score

Based on the daily average ((min + max) / 2):

avg ∈ [18, 24] °C  → 100  (ideal)
avg ∈ [15, 27] °C  → 85
avg ∈ [10, 30] °C  → 70
avg ∈ [5, 32]  °C  → 55
otherwise          → 40

Wind score

Based on max sustained wind speed (km/h), aligned with the Beaufort scale:

< 10 km/h  → 100  (Beaufort 0–2)
< 20 km/h  → 85   (Beaufort 3)
< 30 km/h  → 70   (Beaufort 4)
< 40 km/h  → 50   (Beaufort 5)
< 50 km/h  → 30   (Beaufort 6)
≥ 50 km/h  → 10   (Beaufort 7+)

Precipitation score

score = 100 - precipitation_probability_max
if precipitation_sum > 10 mm  → score -= 20
else if precipitation_sum > 5 mm → score -= 10
score = max(0, score)

Weather code score

Based on WMO weather interpretation codes:

code ≤ 1   (clear / mainly clear) → 100
code ≤ 3   (partly cloudy)        → 80
code ≤ 48  (fog)                  → 60
code ≤ 57  (drizzle)              → 45
code ≤ 67  (rain)                 → 35
code ≤ 77  (snow)                 → 30
code ≤ 86  (showers)              → 25
code ≥ 95  (thunderstorm)         → 15

Composite scores

Three composite scores are derived from the four sub-scores using fixed weights:

Travel Score

temp   × 0.40
+ wind   × 0.20
+ precip × 0.30
+ code   × 0.10

Heaviest on temperature — comfort during sightseeing dominates.

Outdoor Score

temp   × 0.30
+ wind   × 0.30
+ precip × 0.30
+ code   × 0.10

Equal weighting — exposure-sensitive activities like hiking and cycling.

Photography Score

code   × 0.40
+ wind   × 0.30
+ precip × 0.20
+ temp   × 0.10

Cloud type defines light; wind affects tripod stability.

Overall score = (Travel + Outdoor + Photography) / 3, rounded.

Golden Hour Photography Score

A dedicated formula for /golden-hour/[city] pages. Starts at 100 and applies graduated penalties:

Weather code:
  code = 0    → -2  (clear, no dramatic clouds)
  code ≤ 2    → +5  (partly cloudy — IDEAL for golden hour)
  code = 3    → -8  (overcast)
  code 45–48  → -18 (fog)
  code 51–57  → -25 (drizzle)
  code 61–67  → -35 (rain)
  code ≥ 80   → -40 (showers / storms)

Wind (segmented penalty, capped at -45):
  ≤ 12 km/h   → 0
  12–25 km/h  → 0.6 × excess
  25–40 km/h  → +1.0 × excess
  40–55 km/h  → +1.4 × excess
  > 55 km/h   → +1.8 × excess

Precipitation:
  if probability > 20%  → -(prob - 20) × 0.15

Temperature:
  if avg < 5°C or > 35°C → -3

final = clamp(0, 100, round(score))

Activity scoring

Each activity (hiking, beach, city, photography, skiing) has its own threshold profile. Penalties accumulate but are capped at 60 total points.

ActivityMax windMax precipTemp rangeMax precip prob
Hiking40 km/h5 mm5–32 °C40%
Beach30 km/h2 mm20–40 °C30%
City50 km/h10 mm0–35 °C50%
Photography35 km/h2 mm−10–40 °C35%
Skiing35 km/h50 mm−20–5 °C100%

Penalties scale with how far conditions exceed each threshold. Activity-specific bonuses apply for ideal conditions (e.g., +8 for photography under clear skies, +8 for beach when 25–32 °C and clear).

Recommendation logic

Numerical scores convert to one of four labels — but weather codes can override the label downward:

Severe weather (rain, showers, thunderstorm):
  score ≥ 60  → "fair"
  otherwise   → "poor"

Mild bad weather (drizzle, fog):
  score ≥ 70  → "good"
  score ≥ 40  → "fair"
  otherwise   → "poor"

Snow:  treated as mild bad weather
Clear / partly cloudy:
  score ≥ 80  → "excellent"
  score ≥ 60  → "good"
  score ≥ 40  → "fair"
  otherwise   → "poor"

This is why a 78-point day with rain shows as "fair," not "good." The cap is intentional and prevents misleading recommendations.

Forecast reliability

Forecast confidence drops linearly with day index, with a floor at 60%:

reliability(day) = max(60, 95 - day_index × 5)

≥ 85%  → "Very High"  (days 1–2)
≥ 75%  → "High"       (days 3–4)
otherwise → "Medium"  (days 5+)

For "Most Stable," "Sunniest," and "Least Windy" rankings we deliberately limit the candidate set to days 1–7. Beyond that, sub-daily variation in the underlying models loses precision.

Limitations & honest disclosures

  • •Daily resolution. Composite scores use daily aggregates. A morning thunderstorm followed by a clear afternoon may still show as "fair" overall.
  • •No microclimate adjustments. Coastal vs. inland differences within the same city are not modelled.
  • •No air quality. Pollution, pollen, and visibility from haze are not factored into scores.
  • •Personal preference varies. Our "ideal" temperature band of 18–24 °C is calibrated for general travel comfort. Cold-weather travelers and beach-goers will weight differently.
  • •Not for safety-critical decisions. For aviation, marine, or severe-weather planning, always consult official meteorological agencies.

Authorship & review

Snap Weather Editorial Team

Snap Weather Conditions is built and maintained by an independent team focused on travel-decision tooling. The scoring methodology is informed by published meteorological standards — the WMO weather interpretation codes for conditions, the Beaufort scale (0–12) for wind, and conventional photography guidance for golden-hour timing and light quality. We do not employ certified meteorologists; instead we apply transparent, documented thresholds anyone can verify against the source code.

Review process

Every formula in this document mirrors the production code in src/services/scoringService.ts and src/components/golden-hour/photographyScore.ts. When we change a threshold, this page is updated in the same release. Last full review: April 2026.

Corrections & feedback

Spot a formula that doesn't match what you see in the app? See our contact page. We treat methodology bugs as priority fixes.

Related reading