Skip to content

Guides

NWP forecasts in TypeScript

Status: deferred in v1.x. forecastNwp() in @mostlyrightmd/weather exists as a typed stub so callers can write code against the stable signature today, but every call throws NwpNotAvailableError. For gridded NWP today, use the Python SDK (mostlyrightmd>=1.0), which wires the NCEP family end-to-end.

NeedPath
Gridded NWP (HRRR, GFS, NBM, …) right now✅ Python SDK
MOS forecasts for 7 major US stations (KNYC, KLAX, KORD, KMIA, KDEN, KSEA, KATL)iemMosForecasts() in TS
MOS forecasts for any station with IEM MOS coverageiemMosForecasts() in TS
Gridded NWP in the browser / Node.js⏳ TS support tracked for v2.0+
The type signature so you can write forward-compatible codeforecastNwp() (TS) — call it, catch NwpNotAvailableError

GRIB2 is the binary format the world’s NWP centers (NOAA, ECMWF, MSC, …) use to publish gridded forecasts. Decoding GRIB2 requires one of:

  • eccodes — the C library used by everyone, including ECMWF itself. No browser port; native-only.
  • cfgrib — Python wrapper around eccodes. Native-only.
  • A WASM port of eccodes — exists as a research project, but compile-time cost and bundle size (>5 MB even with aggressive tree-shaking) are impractical for a v1.x SDK.

The Python SDK depends on cfgrib + xarray and decodes GRIB2 server-side or on the user’s laptop where native binaries are available. The TS SDK runs in browsers and Node.js where eccodes-class native bindings are not available out-of-the-box, and a WASM-shipped decoder would inflate the SDK’s bundle by 50× for a feature most browser callers never use.

We’re tracking the WASM-GRIB2 ecosystem and will land the execution body in v2.0+ once a viable decoder ships. The function signature is stable today — your code keeps working when the runtime upgrades.

forecastNwp() throws NwpNotAvailableError, which is a subclass of DataAvailabilityError (so existing catch-all handlers continue to work):

import { forecastNwp } from "@mostlyrightmd/weather";
import { NwpNotAvailableError } from "@mostlyrightmd/core";
try {
const grid = await forecastNwp("KNYC", "gfs");
} catch (e) {
if (e instanceof NwpNotAvailableError) {
console.warn(`[NWP deferred] station=${e.station} model=${e.model}`);
console.warn(e.hint);
// Fall through to iemMosForecasts() if your station has MOS coverage.
} else {
throw e;
}
}

The thrown instance carries typed .station and .model properties for log/error attribution — no message parsing required.

Back-compat catch via DataAvailabilityError

Section titled “Back-compat catch via DataAvailabilityError”

Pre-existing code that catches DataAvailabilityError still works:

import { DataAvailabilityError } from "@mostlyrightmd/core";
try {
await forecastNwp("KNYC", "gfs");
} catch (e) {
if (e instanceof DataAvailabilityError && e.reason === "model_unavailable") {
// Same path; .station / .model not surfaced through this catch.
}
}

Workaround: IEM MOS for 7 major US stations

Section titled “Workaround: IEM MOS for 7 major US stations”

If your station is one of KNYC, KLAX, KORD, KMIA, KDEN, KSEA, KATL (or any station IEM MOS covers), iemMosForecasts() gives you MOS-based forecasts that solve most use cases:

import { iemMosForecasts } from "@mostlyrightmd/weather";
const rows = await iemMosForecasts("KNYC", "2026-05-01", "2026-05-07", {
model: "nbe",
});
console.log(rows[0].tempC, rows[0].source); // 20.0, "iem.archive"

MOS isn’t gridded — it’s per-station point forecasts derived from the underlying NWP run — but for settlement / station-level prediction-market work it’s typically the right granularity anyway.

For everything else, the Python SDK wires the NCEP family end-to-end (the mostlyrightmd-weather package, included with your private-beta invite):

from mostlyright.weather import forecast_nwp
df = forecast_nwp("KNYC", "gfs", cycle="2026-05-27T12:00:00Z", fxx=24)
print(df[["station", "valid_time", "temp_c"]])

See the Forecasts guide for the full Python-side documentation including wiring-status tables and rate-limit guidance.

Supported models (signature-only in TS today)

Section titled “Supported models (signature-only in TS today)”

The NwpModel TypeScript type accepts all 24 models from schema.forecast_nwp.v1 so your code is forward-compatible:

NCEP family (11 — all wired in Python)hrrr · hrrrak · gfs · gefs · gdas · nbm · rap · rrfs · rtma · urma · cfs

ECMWF family (4 — reserved)ecmwf_ifs_hres · ecmwf_ifs_ens · ecmwf_aifs_single · ecmwf_aifs_ens

MSC Canadian family (5 — live-only)hrdps · rdps · gdps · geps · reps

NOMADS-only family (4 — reserved)hafs · nam · href · hiresw

For wiring status and historical-depth bounds, see Forecasts § Supported NWP models.

  • v1.x (today): signature stable, throws NwpNotAvailableError. MOS workaround for 7 major US stations.
  • v2.0+ (planned): GRIB2 decode lands once the WASM-GRIB2 ecosystem matures (eccodes-wasm or equivalent reaches production quality and acceptable bundle size). Migration is a runtime upgrade — no signature break, no caller code changes required.
  • Anytime in between: if you have a working browser/Node GRIB2 decoder at a reasonable bundle size, let us know.