Frequently asked questions
How does it differ from other wind-mapping solutions?
Mapbox Wind Layer relies on Mapbox’s proprietary Tiling Service to convert GRIB wind data into
raster arrays tiled at multiple zoom levels. At high zoom (e.g. greater than 12), covering the extent can require a
very large number of tiles — processing cost grows quickly, and pipelines sometimes hang or get killed before they
finish. If you cap tiles at zoom 12 instead, particles look like blurry boxes sliding across the map when users zoom
in to village, neighborhood, or street level — an aesthetic that is hard to accept for detailed views.
Open-source alternatives
|
mapbox-exif-layer |
maplibre-gl-wind |
sakitam-gis/maplibre-wind |
| MapLibre v5 / v6 support |
Yes (with mapRuntime set to maplibre in constructor; v5 from v1.2.1+, v6 from v1.3.5) |
Yes (via MapboxOverlay of deck.gl) |
No (only works for MapLibre v3) |
| MapLibre Globe Projection |
Yes |
No |
No |
| Particle colors vary by actual speed |
Yes |
Yes |
No |
| Particle has tails |
Yes |
No |
Yes |
| GeoTIFF support |
Yes (sample code and data are provided; v1.3.1+) |
No |
Yes (mentioned in the doc, but no sample code or data supplied) |
| Image source support |
Single JPEG or PNG |
Single PNG |
Single or tiled JPEG or PNG |
| Browser on mobile device support |
Yes (native) |
Yes (depends on deck.gl) |
No (very likely to lose WebGL context) |
| NA/No data cells handling |
Store 0 in B-band for NA cells (v1.1.0+) |
Store 0 in A-band for NA cells |
Require GeoJSON mask valid or invalid area and supply mask parameter to the layer constructor |
See more in
Assessing packages for mapping wind as particle motion layer in MapLibre.
How are JPEG/PNG image sources encoded?
A JPEG or PNG used as a source is not a normal photo — it stores a normalized weather grid in
three 8-bit RGB bands (0–255 per channel). For wind (ParticleMotion),
u-velocity is min–max normalized to 0–255 in the R band and v-velocity in the
G band; no-data cells use B = 0 (valid cells use
B = 255). For a smooth raster (SmoothRaster), the scalar attribute is
normalized to 0–255 in the R band; no-data cells use B = 255
(valid cells use B = 0).
The layer also needs the physical min and max values used when encoding (before
normalization). You can supply them in either of two ways:
- EXIF — write min/max to JPEG
ImageDescription (the classic
“EXIF-enabled JPEG” path; see
Method 2
in the docs).
- Constructor (v1.3.2+) — pass
scalarValueRange on
SmoothRaster or velocityRange on ParticleMotion when the image has no
EXIF metadata (Method 1). If EXIF is present, it takes precedence.
See
docs/jpeg-source.md
for encoding rules, both min/max workflows, and ready-to-use pipeline scripts.
I would like to visualize a GeoTIFF file — can I use this package?
Yes. The package supports GeoTIFF in the browser with no tile server — which kind depends on your file:
- Scalar / grayscale (temperature, elevation, wind u/v, …) —
SmoothRaster or ParticleMotion. See scalar GeoTIFF docs.
- RGB / RGBA imagery (aerial, orthomosaic, true-color satellite) —
RgbGeoTiff. See RGB GeoTIFF docs.
That path is best for small grids, demos, data previews, and other
non-production use. The layer downloads the entire GeoTIFF on load (no COG range requests or tiling), so large files or maps at many zoom levels are a poor fit.
For production, use a standard Mapbox/MapLibre raster tile source instead:
- Pre-generated MBTiles — build tiles with rio-mbtiles or QGIS Raster → Generate XYZ Tiles (MBTiles), then serve with mbtileserver. For scalar GeoTIFF, assign RGB(A) colors from the attribute first (e.g. rasterio + NumPy) before generating the tileset.
- COG + tile server — TiTiler (or GeoServer / similar) serves tiles directly from a Cloud Optimized GeoTIFF without pre-generating MBTiles.
- MapLibre serverless COG — host a COG on static storage and use maplibre-cog-protocol for range-request tiling in the client (no tile server).
For wind maps, should I use JPEG/PNG or GeoTIFF?
Properly encoded JPEG/PNG rasters are much smaller than GeoTIFFs. On this site’s NOAA NAM NEST CONUS demo grid
(2269×976), wind is ~332 KB as JPEG vs ~8.9 MB as
ZSTD-compressed float32 GeoTIFF — a big difference for storage and download when you serve many forecast
timesteps.
GeoTIFF is still a practical starting point: a familiar gdalwarp step gets you a map without learning custom JPEG band encoding — a quick way to validate the layer and build confidence before moving to encoded images for production.
- Prefer JPEG/PNG when you need many timesteps (multi-hour forecasts), a large grid, or want minimal hosting cost. Min/max velocity metadata can come from EXIF or constructor
velocityRange.
- Prefer GeoTIFF (EPSG:4326, float32 u/v bands, compressed) when you want a GIS-friendly pipeline without custom image encoding, have a smaller study area, and only a few timesteps. Extra float precision is often not visible in everyday visualization though.
Can GeoTIFF be used for smooth, non-blocky, linear-interpolated display?
No — not with SmoothRaster in this package. For smooth weather display (temperature, humidity, precipitation, …), use a
properly encoded JPEG/PNG
source. The grid is uploaded as an 8-bit RGBA texture with linear filtering, so the GPU bilinearly blends between neighboring cells and the layer looks smooth when zoomed in.
Scalar GeoTIFF on SmoothRaster is a separate use case: a preview path with native grid resolution and
nearest sampling on float32 data (WebGL does not reliably support linear filtering on float textures). Cell edges stay visible when zoomed in even though colormap stops are interpolated. See
scalar GeoTIFF docs
and the
GeoTIFF production note above
for alternatives at scale.
Can this package be used with Leaflet or OpenLayers?
No. It targets Mapbox GL JS and MapLibre GL JS only — both WebGL map SDKs
with a similar custom-layer API that this package implements. Leaflet and OpenLayers use a different rendering
model and are not supported.
Do you provide ready-to-map wind data?
Yes. Global NOAA GFS 0.25° forecasts are published as EXIF JPEGs you can pass straight to
ParticleMotion and SmoothRaster — no tile server. They are free for non-commercial
and commercial use; add custom attribution for
NOAA GFS
and mapbox-exif-layer. The product updates every 6 hours (00 / 06 / 12 / 18 UTC cycles).
Layer URLs (copy one per source; HH is 00–23 UTC):
https://www.mapbox-exif-layer.com/gfs/0p25/wind/wind_{YYYYMMDDHH}.jpeg
- 10 m UGRD + VGRD, m/s (
ParticleMotion, unit: 'mps')
https://www.mapbox-exif-layer.com/gfs/0p25/temperature/temperature_{YYYYMMDDHH}.jpeg
- 2 m TMP, °C (
SmoothRaster)
https://www.mapbox-exif-layer.com/gfs/0p25/rh/rh_{YYYYMMDDHH}.jpeg
Catalog for a time slider (copy this URL; hourly f000–f120, then 3-hourly through
f384):
https://www.mapbox-exif-layer.com/gfs/0p25/status.json
Build slider timestamps as hourly steps from init_unix through hourly_until_unix.
available_from is only a lookback stamp (init minus 96 h), not an inventory. Old JPEGs are not
deleted by the pipeline; an S3 lifecycle rule expires them about 6 days after last modification, so times
before init are not guaranteed.
Globe time-slider demo:
live
·
source.
To run the same NOAA → JPEG conversion on your own schedule, see
pipeline/gfs.
Field-by-field status.json notes are in the
README GFS section.