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.
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.
- 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
| 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 |
- 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.
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 — 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 — 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=autoso 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).
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.
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.
- 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.
- 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.
| 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) |
- Node.js 20+
- npm
npm install
npm run devOpen http://localhost:5173 in your browser.
npm run build
npm run previewRequires 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 assembleDebugThe APK will be at android/app/build/outputs/apk/debug/app-debug.apk.
Install on a connected device:
adb install app-debug.apknpm run build
npx cap sync ios
npx cap open iosIn 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.
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
MIT
- Weather data: Open-Meteo — free and open-source weather API
- Built with Vite, React, Capacitor, Recharts