Mountain weather for snowboarders and skiers, worldwide.
Because "70% chance of snow" doesn't tell you whether to call in sick.
๐ Try it live โ
PowderCast is a hyper-local forecast for 722 ski resorts in the US, the Alps, the Dolomites, the Pyrenees and Japan. It answers the only question that matters at 6am:
Where should I ride, and which day?
It knows your ski pass, so it won't recommend a mountain you'd need a second mortgage to get into. It knows whether it's raining at the base, so you won't drive three hours to ski on a Slurpee. And it's a fully static site with no backend, no API keys and no database. Nothing to page anyone about.
| Where | Resorts | What the locals call good snow |
|---|---|---|
| ๐จ๐ญ Alps (FR ยท CH ยท AT ยท DE ยท IT) | 387 | Pulverschnee |
| ๐๏ธ US Rockies | 79 | Champagne powder |
| ๐ US East & Midwest | 68 | "Loud powder" (ice) |
| ๐ฎ๐น Dolomites | 53 | Whatever's under the espresso |
| ๐ฏ๐ต Japan | 50 | JaPow |
| ๐ฒ US West | 46 | Sierra Cement (with love) |
| ๐ฆ๐ฉ Pyrenees | 39 | Pols / polvo |
| View | What it's for |
|---|---|
| โฐ๏ธ Single Mountain | Everything about one resort, with the verdict on a phone's first screen |
| ๐ Compare Regions | Every resort in a region side by side, ranked by Ride Score, plus a map |
| ๐๏ธ 7-Day Planner | Resorts ร days in one grid, so the best mountain and the best day stand out |
| โญ Compare Favorites | Your shortlist, head to head |
One number from 0 to 100 built from new snow, snow quality, wind, visibility and temperature. It's shared by every view, so the same day can't score 55 in one tab and 43 in another. (That happened once. It's in the commit history. We don't talk about it.)
| Score | Verdict |
|---|---|
| ๐ | Epic Conditions: send the "I'm sick" email now |
| ๐ | Great: worth the drive |
| ๐๏ธ | Fair Groomers: corduroy and coffee |
| Marginal: good day to wax your board | |
| ๐ง | Poor: good day to sit in the lodge |
- Today at a glance: the Ride Score plus the four numbers that decide the day (new snow, temperature, gusts, snow line), all above the fold on a phone
- Snow line: where the freezing level sits between base and summit. If it's in the middle, the top gets powder and the bottom gets a car wash. This is the most important number in the Alps and the maritime US ranges.
- Snow forecast: 24h and 7-day totals with hourly detail, plus a ๐จ Powder Alert at 6"+
- Base depth: settled snow already on the ground
- Wind & aspect: which slopes are wind-loaded (deep) and which are scoured (firm enough to hear coming)
- Firn window: spots the overnight-freeze, daytime-thaw spring corn cycle and tells you when to be on it. Too early is ball bearings, too late is mashed potatoes.
- Base โ summit toggle: real elevation-corrected numbers, not the same forecast twice
- ๐ฅถ wind chill and frostbite warnings, ๐จ wind-hold risk, โ๏ธ bluebird detector
- ๐ฌ Pro View: every raw number, for people who read avalanche bulletins for fun
Tag your Ikon (68 resorts), Epic (43) or Mountain Collective (16) pass and the whole app narrows to mountains you can ride without buying another lift ticket.
One tap ranks resorts by distance. "Nearby" also works as a region in the planner and comparison, and there's a map with pins coloured by Ride Score. Your location stays in memory and never goes into the URL, so a shared link doesn't tell your friends where you live.
- ๐ Metric or imperial, defaulting to what the resort's locals use. Every view follows the setting, including the ones that used to forget.
- ๐ Shareable links: resort, elevation, view and region all live in the URL, so back/forward, refresh, bookmarks and the share button just work
- โญ Favourites and auto-refresh that pauses when the tab is hidden
- ๐น Live webcams for 25 major resorts, and website links for the other 669
| Region | Provider | Model |
|---|---|---|
| United States | National Weather Service | NDFD gridpoints |
| French Alps, Pyrenees | Open-Meteo | Mรฉtรฉo-France AROME HD (1.5km) |
| Switzerland, Austria, Bavaria, Dolomites | Open-Meteo | DWD ICON-D2 (2km) |
| Japan | Open-Meteo | JMA Seamless (5km) |
| Scandinavia (forecast-ready, no resorts yet) | Open-Meteo | MET Norway Nordic (1km) |
The provider is picked automatically from the coordinates. Open-Meteo steps in if NWS is having a day. Neither needs an API key.
Resort data comes from OpenSkiMap, an open dataset built from OpenStreetMap that includes real piste elevations.
nvm use # Node 22 (see .nvmrc)
yarn install
yarn dev # โ http://localhost:3000public/resorts.json is committed, so you only need yarn build:resorts if
you want to regenerate it from OpenSkiMap.
Pushing to main runs the unit tests, builds the static export and deploys to
GitHub Pages (deploy.yml).
app/ Next.js App Router (static export)
components/ UI: cards, views, map, planner grid
hooks/
useForecast.ts Single + multi-resort fetching, caching, fallback
usePlanner.ts Resort ร day outlook grid
useGeolocation.tsx "Near me", held in memory only
useUrlState.ts View state โ URL
useUnits.tsx Metric/imperial preference
usePassFilter.ts "My pass" preference
lib/
providers/ WeatherProvider implementations + routing
nws.ts US National Weather Service
openMeteo.ts Global, with regional high-res model selection
types.ts Resort + the normalized SI forecast model
conditions.ts Normalized SI โ rider-facing display model
scoring.ts The one and only Ride Score
series.ts Window reductions over the hourly series
planner.ts Multi-day outlook
lapseRate.ts Elevation correction for providers that need it
nearby.ts Great-circle distance ranking
urlState.ts URL parse/serialize
units.ts Unit-system-aware formatting
snowVocabulary.ts Region-specific snow terminology
passes.ts Ski pass metadata and filtering
data/passes.json Ikon / Epic / Mountain Collective rosters
data/webcams.json Curated webcam overlay
scripts/build-resorts.js Regenerates public/resorts.json from OpenSkiMap
Every provider's data is converted to SI as soon as it arrives (ยฐC, mm, km/h, m) and converted to display units exactly once, at the edge.
This matters because the providers disagree in ways that fail silently. NWS reports snowfall in millimetres, Open-Meteo in centimetres, and snow depth in metres. An earlier version ran NWS millimetres through a centimetre conversion, overstated every snow total by 10ร, and fired Powder Alerts on 0.6" of snow. Some people probably drove to a mountain over that. Normalizing once, inside the provider, keeps that class of bug out of the components.
A resort's base and summit coordinates are usually a few hundred metres apart,
well inside a single 2.5km NWS grid cell. Palisades Tahoe's base and summit both
resolve to grid REV 28,94, so a coordinate-only "dual point" forecast gives
you the same forecast twice.
What actually separates them is elevation. Open-Meteo accepts an
elevation parameter and downscales properly. NWS can't, so PowderCast applies
a lapse-rate correction and labels that view as modelled.
data/passes.json holds the Ikon, Epic and Mountain Collective rosters with
access tiers (unlimited / N days / partner).
โ ๏ธ Pass affiliations change every season. Resorts join, leave and swap tiers every year. The file records which season it was verified against, so re-check it against ikonpass.com and epicpass.com before each winter.
yarn verify:passes # exits non-zero if any roster entry matches no resortAn unmatched entry usually means the resort is below the size threshold (most Midwest Epic hills are), its upstream name changed, or it left the pass.
| Command | Description |
|---|---|
yarn dev |
Development server |
yarn build |
Static export to ./out |
yarn lint |
ESLint |
yarn test |
Unit tests (no network) |
yarn test:providers |
Live provider contract tests (hits the network) |
yarn build:resorts |
Regenerate public/resorts.json from OpenSkiMap |
yarn build:resorts --refresh |
Re-download the source dataset first |
yarn verify:passes |
Check every pass entry still matches a resort |
yarn generate:icons |
Rebuild the favicon and app icons |
yarn test # 126 assertions across 7 suites, no network, ~15s
yarn test:providers # live contract tests against NWS + Open-MeteoThe unit suite runs on synthetic data and a captured NWS gridpoint fixture
(tests/fixtures/nws-gridpoint-REV-28-94.json). It covers NWS processing,
scoring, units and the planner, elevation, the resort schema, URL state and
nearby ranking.
Every case corresponds to a bug that actually shipped. If a test fails, add a case rather than loosening the existing one.
The forecast layer is already global. Adding a country (say, Norway, whose
weather model is already wired up) takes two lines in
scripts/build-resorts.js:
const COUNTRIES = {
// ...
NO: { regionCode: 'scandinavia', timezone: 'Europe/Oslo' },
};Then run yarn build:resorts. If the country needs a new tab, add it to
REGIONS in lib/regions.ts (scandinavia and canada are already there),
and add a high-resolution model to REGIONAL_MODELS in
lib/providers/openMeteo.ts if one covers the area.
Deeper notes are in docs/, including the Pro View,
debugging tips and the
snow accumulation bug post-mortem.
Educational project. Weather data: NOAA/NWS (public domain) and Open-Meteo (CC BY 4.0). Resort data: OpenSkiMap / OpenStreetMap contributors (ODbL). Map tiles: OpenStreetMap contributors.
๐๏ธ Not a substitute for official avalanche bulletins or resort snow reports. PowderCast can tell you it's a powder day. It can't tell you a slope is safe. Check the avalanche forecast, carry the gear and ride with friends.
Made with โ๏ธ and too much coffee by @greenido
If PowderCast finds you a powder day, the first chair is on you.