Skip to content

Repository files navigation

◐ Ensemble

A multi-model weather forecast app that shows you where weather models agree and where they don't.

Most weather apps show you a single forecast and call it a day. Ensemble takes a different approach: it fetches predictions from five independent weather models and displays them side by side, so you can see the full range of what the atmosphere might do.


Why This App Exists

I was tired trying so many weather apps that none of them seemed to predict the weather accurately. This app is trying to close the gap at least, by agreggating 5 models and by "making an average". Sometimes these models wildly disagree and that disagreement is the forecast: genuine uncertainty.

Ensemble gives you that information instead of hiding it behind a single number.


Features

  • 5 weather models fetched in parallel from the Open-Meteo API (no API key needed)
  • Comfort Meter — a single 0–100 human-comfort score from feels-like temperature, humidity and wind, with a plain-language breakdown of why (see Legend)
  • Best window today — scans the ensemble comfort score hour-by-hour and tells you the nicest stretch of daylight still to come
  • Sunrise / sunset + golden hour — local sun times and the morning/evening golden-hour windows for photographers
  • Smart alerts — a conservative heads-up banner for storms, heavy rain/snow, strong gusts, heat, freezing, very high UV, poor air, or high pollen
  • UV index, air quality & pollen — current UV band, European AQI (PM2.5 / PM10) and pollen alongside the ensemble
  • Interactive ensemble charts — temperature, wind speed, and precipitation probability with all model lines overlaid
  • Rolling time windows — toggle between 24 hours, 3 days, and 7 days (see Legend below)
  • 7-day overview — daily summary cards with highs, lows, rain chance, and model spread
  • Model toggle bar — enable/disable individual models to focus on the ones you care about
  • The Models reference — an in-app expandable section explaining who runs each model, where, at what resolution, and why it matters
  • City search + favorites — search by city name and save a favorites list for one-tap switching
  • Follow me (GPS) — optional opt-in that follows your location as you travel, refreshing every 30 minutes (foreground only, battery-conscious)
  • Android app + home screen widgets — installable APK with three selectable widget sizes (Compact / Standard / Detailed), larger fonts, and comfort/UV/air-quality on the Detailed size. The widget follows the location you last viewed in the app.
  • iOS app + WidgetKit extension — Capacitor-based, requires Xcode to build
  • Fully responsive — works on desktop and mobile browsers
  • Dark theme — atmospheric instrument-panel aesthetic, easy on the eyes

The Models

Colour Model Provider Notes
🔴 #E8573A ECMWF IFS European Centre for Medium-Range Weather Forecasts Generally considered the world's best global model
🔵 #3A8FE8 GFS NOAA (US National Weather Service) Widely used, good global coverage
🟢 #4ADE80 ICON DWD (German Weather Service) Strong in Europe, high resolution
🟣 #C084FC ARPEGE Météo-France French national model, good for Western Europe
🟡 #F59E0B UKMO UK Met Office Highlighted with a thicker line : most relevant for UK locations

Legend

What the numbers mean

  • Ensemble Mean — The average temperature across all active models. This is the "best guess" but it hides disagreement.
  • Range (e.g. 12°–16°) — The spread between the coldest and warmest model predictions for the same hour. A tight range means agreement; a wide range means uncertainty.
  • ±X.X° (on daily cards) — Average model spread for that day. Think of it as a confidence margin.

Comfort Meter

Shown on the current conditions card — a single 0–100 score (0 = brutal, 100 = perfect) computed from the ensemble-mean feels-like temperature, humidity and wind. It starts at 100 and subtracts penalties for anything that makes a human uncomfortable, then lists the culprits (e.g. Muggy / humid, Windy, Cold).

Score Label
90–100 Perfect
78–89 Very pleasant
62–77 Pleasant
46–61 So-so
30–45 Uncomfortable
15–29 Harsh
0–14 Brutal

Note: the old temperature-only agreement badge was removed — it conflated "models disagree on temperature" with "the forecast is uncertain", which was misleading (e.g. all models agreeing it won't rain still showed "moderate"). Raw model spread now lives only where it's meaningful: the charts and daily cards.

UV Index, Air Quality & Pollen

  • UV index — ensemble-mean UV with a WHO band: Low (<3), Moderate (3–5), High (6–7), Very high (8–10), Extreme (11+).
  • Air Quality — European AQI from Open-Meteo's air-quality API (a single source, not an ensemble): Good (≤20), Fair (≤40), Moderate (≤60), Poor (≤80), Very poor (≤100), Extremely poor (>100). PM2.5 and PM10 shown in µg/m³.
  • Pollen — strongest of grass / birch / ragweed / alder (grains/m³, Europe only), banded None → Very high.

Best Window Today & Golden Hour

  • Best window today — the app computes the Comfort Meter score for every remaining daylight hour, drops any likely to be rained out (>45% precip probability), finds the peak, and expands outward while comfort stays within 8 points. Shown as a time range + comfort score.
  • Sunrise / sunset — fetched with timezone=auto so the clock times are correct for the selected location, not the app's data timezone.
  • Golden hour — the hour after sunrise and the hour before sunset, when light is warm and soft (great for photos).

Alerts

A deliberately conservative banner near the top. It only appears when something is genuinely worth knowing in the next 24h: thunderstorms, heavy rain/snow, wind gusts ≥ 60 km/h, feels-like ≥ 32° (heat) or ≤ 0° (freezing), daytime UV ≥ 8, AQI > 80, or high pollen. Warnings are amber, informational notes are blue.

Time Range Toggle (24h / 3 Days / 7 Days)

These are rolling windows from the current time, not calendar days. If you open the app at 14:00:

  • 24h shows from 14:00 today to 14:00 tomorrow
  • 3 Days shows the next 72 hours
  • 7 Days shows the full forecast

This avoids the problem of "Today" showing only 15 minutes of data if you check at 23:45.

Charts

  • Temperature Ensemble — The shaded area shows the min/max spread across models. Individual coloured lines show each model's prediction. A dashed purple "Now" line marks the current time.
  • Wind Speed — Same multi-model overlay for wind at 10m height (km/h).
  • Precipitation Probability — Grouped bars comparing each model's rain probability (%). Downsampled to 3-hour intervals for readability.

Why some things look "off"

  • Models can disagree a lot — This is real. If one model shows 8°C and another shows 14°C for the same hour, that's the actual state of the science. It doesn't mean the app is broken.
  • UK Met Office line is thicker — Intentional. For UK locations, the Met Office model has the highest resolution and is most likely to be accurate.
  • Some models may fail to load — Open-Meteo occasionally has issues with specific models. The app shows whatever loaded successfully and reports errors for failures. This is by design — partial data is better than no data.
  • Temperature spread can be 0° — If all models agree exactly, the range collapses. This is a good thing.

Tech Stack

Layer Technology
Frontend React 19, TypeScript, Vite 8
Styling Tailwind CSS v4 (@tailwindcss/vite plugin)
Charts Recharts
Icons lucide-react
Dates date-fns
Native wrapper Capacitor 8
Android widget Kotlin (AppWidgetProvider)
iOS widget SwiftUI (WidgetKit)
Geolocation Capacitor Geolocation plugin (opt-in "follow me")
Weather API Open-Meteo (free, no key)
Air Quality API Open-Meteo Air Quality (free, no key)
Geocoding API Open-Meteo Geocoding forward · BigDataCloud reverse (both free, no key)

Getting Started

Prerequisites

  • Node.js 20+
  • npm

Install and run

npm install
npm run dev

Open http://localhost:5173 in your browser.

Build for production

npm run build
npm run preview

Build Android APK

Requires Android Studio (for the JDK and SDK):

npm run build
npx cap sync android
export JAVA_HOME="C:/Program Files/Android/Android Studio/jbr"  # adjust for your system
cd android && ./gradlew assembleDebug

The APK will be at android/app/build/outputs/apk/debug/app-debug.apk.

Install on a connected device:

adb install app-debug.apk

Build iOS (requires Mac)

npm run build
npx cap sync ios
npx cap open ios

In Xcode, add the EnsembleWidget target (File → New → Target → Widget Extension), replace the generated code with ios/App/EnsembleWidget/EnsembleWidget.swift, configure the App Group group.com.ensemble.weather, and build.


Project Structure

src/
  types/weather.ts             — TypeScript interfaces
  config/models.ts             — Model configs + metadata, WMO codes, UV/AQI bands
  hooks/useWeatherData.ts      — Ensemble fetch, air-quality fetch, timeline merging, stats
  utils/
    comfort.ts                 — Comfort Meter algorithm (0–100 score + factors)
    insights.ts                — Best-window, golden-hour and alert computation
    prefs.ts                   — Favorites / follow-me / last-location persistence
    geolocation.ts             — Opt-in GPS + reverse geocoding
    widget.ts                  — Native bridge to refresh the home-screen widget
  components/
    Header.tsx                 — App name, location button (GPS indicator), refresh
    Alerts.tsx                 — Smart-alert banner (storms, heat, UV, air, pollen…)
    CurrentConditions.tsx      — Temp, Comfort Meter, UV, air quality, pollen, wind
    ComfortMeter.tsx           — Comfort score badge + factor breakdown
    TodayInsights.tsx          — Best window today + sunrise/sunset + golden hour
    DayOverview.tsx            — 7-day summary grid
    ModelToggle.tsx            — Enable/disable individual models
    ModelLegend.tsx            — Expandable per-model reference (agency, base, resolution)
    TimeRangeToggle.tsx        — 24h / 3 Days / 7 Days selector
    TemperatureChart.tsx       — Ensemble temperature chart
    WindChart.tsx              — Multi-model wind chart
    PrecipChart.tsx            — Precipitation probability bars
    LocationEditor.tsx         — City search + favorites + follow-me + manual coords
    Footer.tsx                 — Ensemble forecasting explainer
  App.tsx                      — Root component (location, favorites, follow-me loop)
android/                       — Capacitor Android project
  .../widget/WidgetShared.kt   — Shared fetch + comfort/UV/AQI + reads live location
  .../widget/EnsembleWidget.kt — Standard 4x2 widget
  .../widget/CompactWidget.kt  — Compact 2x1 widget
  .../widget/DetailedWidget.kt — Detailed 4x3 widget (comfort, UV, air quality)
  .../WidgetBridgePlugin.kt    — Capacitor plugin to refresh widgets on location change
ios/                           — Capacitor iOS project + WidgetKit extension

License

MIT


Credits

About

Weather App

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages