windy-plugin-weather-why Svelte Themes

Windy Plugin Weather Why

Click any spot on a Windy map and find out why the weather is doing what it is. 13 hand-written pattern explanations with clickable cross-layer toggles.

windy-plugin-weather-why

A Windy.com plugin that turns the weather on the map into a moment of genuine understanding. Click any spot on any Windy layer (wind, rain, pressure, temperature, satellite, CAPE, gust, AQ, dust, waves, radar, clouds). The plugin recognises the visual pattern you're looking at and explains it in a four-beat card:

Title → 2–3 sentence mechanismCheck next: clickable cross-layer toggles → Remember: model-vs-observation caveat

The "Check next" buttons actually flip Windy's layer so you can confirm the explanation in real time. All explanation text is hand-written, parameterised for live data, and verified against NOAA / AMS / peer-reviewed meteorology sources.

What it recognises

13 patterns + a "What you're seeing" fallback on covered layers:

Pattern Trigger layer
Cyclonic inflow around a low (+ tropical-cyclone override for sub-985-hPa systems in the tropics) Wind (surface)
Strong wind in a tight pressure gradient Wind
Rain in a line (front / squall) Rain, RainAccu, Radar
CAPE present but the sky is quiet (cap / CIN) CAPE
Clouds without rain (virga, cirrus, cloud shield) Radar, Satellite, Clouds, Cloudtop
Sharp temperature line (front signature) Temperature
Jet stream Wind 250h / 300h
Haze / dust plume (regional transport) cAQI, PM2.5, PM10, Dust
High gust factor Gust
Orographic rain & rain shadow Rain (elevated terrain)
Swell vs wind waves (distant-storm energy) Waves, Swell
Sea breeze (afternoon onshore flow) Wind (coastal)

When no specific pattern fires on a covered layer, a "What you're seeing" card explains the layer + local data point.

Tech

  • Pure client-side. Svelte + TypeScript. No backend.
  • Data: Open-Meteo (forecast, upper air, marine, air quality). Keyless, free.
  • Build size: ~52 KB minified.

Dev loop

npm install                       # one-time
npm start                         # serves https://localhost:9999/plugin.js

Then:

  1. Open https://localhost:9999/plugin.js once in a browser to accept the self-signed cert.
  2. Visit https://www.windy.com/dev.
  3. Paste https://localhost:9999/plugin.js in the "Plugin URL" field. The right-hand pane opens.
  4. Edits to src/plugin.svelte, src/pluginConfig.ts, or anything under src/lib/ hot-reload.

CORS friction loading localhost:9999 into windy.com/dev? Add CORS headers to the Rollup dev server config (community forum has working examples).

If npm install fails with EACCES on ~/.npm/_cacache/: fix with sudo chown -R $(whoami) ~/.npm, or use a fresh cache: npm install --cache /tmp/npm-cache.

Build for distribution

npm run build                     # outputs dist/plugin.{js,min.js}

Architecture

src/
├── plugin.svelte                 # main UI: click → fetch → detect → render
├── pluginConfig.ts               # plugin metadata
└── lib/
    ├── types.ts                  # Facts schema, PatternModule contract, WindyOverlay union
    ├── geo.ts                    # haversine, bearing, compass8
    ├── facts.ts                  # 5 parallel Open-Meteo fetches (forecast, upper-air,
    │                             #   49-point MSL-pressure grid, air quality, marine)
    └── patterns/
        ├── index.ts              # MODULES registry, pickPattern dispatcher,
        │                         #   CATALOG, getLayerDefault
        ├── cyclonic_inflow.ts    # + tropical-cyclone override
        ├── tight_gradient.ts
        ├── rain_in_a_line.ts
        ├── cape_no_storms.ts
        ├── radar_satellite_mismatch.ts
        ├── sharp_temperature_line.ts
        ├── jet_stream.ts
        ├── haze_dust_plume.ts
        ├── wind_gust_factor.ts
        ├── orographic_rain.ts
        ├── swell_vs_wind.ts
        ├── sea_breeze.ts
        └── layer_defaults.ts     # "What you're seeing" cards per layer

Click resolution

  1. Pattern matchpickPattern(activeLayer, facts) runs every module whose appliesToLayers includes the current overlay; highest-confidence match wins.
  2. Layer default — if no pattern fires, getLayerDefault(layer, facts) renders a "What you're seeing" card explaining the layer.
  3. Layer not yet supported — UI fallback names which layers ARE covered.

Each pattern module exports detect(facts, ctx), visual(map, facts, params) (returns a cleanup function; currently noop everywhere — Windy's own layers carry the visualisation), and content(facts, params) returning a PatternCard (title / mechanism / checkNext / remember).

License

MIT — see LICENSE.

Publishing to Windy's plugin gallery additionally grants Windy a perpetual sublicensable license to the plugin source (standard for the plugin gallery). Currently private: true in src/pluginConfig.ts — distributable via personal share URL only until that flag is flipped and the publish action is run.

Top categories

Loading Svelte Themes