# Overview

WeatherLayers consists of two products, that can be used either together or separately:

* [WeatherLayers GL](/weatherlayers-gl) is a library of high-performance interactive weather visualization layers and controls, which can be customized in real-time and supports integration with major mapping libraries. The library can be used either with custom self-hosted data or with [WeatherLayers Cloud](/weatherlayers-cloud).
* [WeatherLayers Cloud](/weatherlayers-cloud) is a cloud service providing visualization-ready weather data from global public weather data sources.


# WeatherLayers GL

WeatherLayers GL is a library of high-performance interactive weather visualization layers and controls, which can be customized in real-time and supports integration with major mapping libraries. The library can be used either with custom self-hosted data or with [WeatherLayers Cloud](/weatherlayers-cloud).

Peer dependencies:

* [deck.gl](https://deck.gl) >= 9.2.0
* [luma.gl](https://luma.gl/) >= 9.2.0
* [geotiff.js](https://github.com/geotiffjs/geotiff.js/) >= 3.0.0 (if loading GeoTIFF images)
* [maplibre-gl-js](https://github.com/maplibre/maplibre-gl-js) >= 5.0.0 or (if using MapLibre Globe projection) or >= 3.0.0 (if using MapLibre with deck.gl interleaved to support WebGL2)
* [mapbox-gl-js](https://github.com/mapbox/mapbox-gl-js) >= 3.0.0 (if using Mapbox with deck.gl interleaved to support WebGL2)

### Versioning

WeatherLayers GL uses [Calendar Versioning](https://calver.org/) schema `YYYY.MM.MICRO`, e.g. `2022.4.0`.

### Compatibility

* deck.gl 9.3 - WeatherLayers GL 2026.5.0-latest
* deck.gl 9.2 - WeatherLayers GL 2025.11.0-2026.2.0
* deck.gl 9.1 - WeatherLayers GL 2025.1.0-2025.8.0
* deck.gl 9.0 - WeatherLayers GL 2024.4.0-2024.9.1


# Quick Start

### Installation

```
npm install weatherlayers-gl
```

GitHub: <https://github.com/weatherlayers/weatherlayers-gl>

### Production Usage

```typescript
import * as WeatherLayers from 'weatherlayers-gl';
```

No license file is necessary to use the library in production anymore.


# Layers

Layers are available as deck.gl plugins. They can be rendered either with standalone deck.gl, or integrated with any supported basemap library. See [Demo](https://demo.weatherlayers.com/).


# Particle Layer

Vector variable rendered as animated particle simulation layer

### Example

![Particle Layer](/files/cPtjSWujhGHYn5mfrUnl)

```javascript
import { Deck } from '@deck.gl/core';
import { ClipExtension } from '@deck.gl/extensions';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureData(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.ParticleLayer({
      id: 'particle',
      // data properties
      image: image,
      bounds: [-180, -90, 180, 90],
      extensions: [new ClipExtension()],
      clipBounds: [-181, -85.051129, 181, 85.051129],
    }),
  ],
});
```

### Data Properties

See [Data properties](/weatherlayers-gl/layers/data#data-properties) common for all layers.

### Style Properties

See [Style properties](/weatherlayers-gl/layers/style-properties) common for all layers.

#### `numParticles`

Type: number, optional

Default: `5000`

Number of the particles. The greater number of particles, the denser particle trails.

#### `maxAge`

Type: number, optional

Default: `100`

Max age of the particles in frames. The greater max age, the longer particle trails.

#### `speedFactor`

Type: number `0-1`, optional

Default: `1`

Speed factor of the particles. The greater speed factor, the longer particle trails.

#### `width`

Type: `number`, optional

Default: `1`

Width of the line. See [LineLayer getWidth](https://deck.gl/docs/api-reference/layers/line-layer#getwidth).

#### `color`

Type: color `[number, number, number, number?]`, optional

Default: `[255, 255, 255]`

Color of the line. See [LineLayer getColor](https://deck.gl/docs/api-reference/layers/line-layer#getcolor).

#### `palette`

Type: color palette text or array, optional

Palette used to interpolate values to colors.

Formats:

* text (`string`) - see [Text format](https://github.com/weatherlayers/cpt2js#text-format) for details
* array (`[number, PaletteColor][]`) - `PaletteColor` is any object accepted by [Chroma.js constructor](https://vis4.net/chromajs/#chroma)


# Raster Layer

Variable rendered as a color overlay

### Example

![Raster Layer](/files/FI99a8FGyX6E7WwH2Fo0)

```javascript
import { Deck } from '@deck.gl/core';
import { ClipExtension } from '@deck.gl/extensions';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureData(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.RasterLayer({
      id: 'raster',
      // data properties
      image: image,
      bounds: [-180, -90, 180, 90],
      // style properties
      palette: [
        [0, [255, 255, 255]],
        [5, [127, 255, 255]],
        [10, [127, 255, 127]],
        [15, [255, 255, 127]],
        [20, [255, 127, 127]],
        [25, [127, 0, 0]],
      ],
      extensions: [new ClipExtension()],
      clipBounds: [-181, -85.051129, 181, 85.051129],
    }),
  ],
});
```

### Example: Picking

```javascript
import { Deck } from '@deck.gl/core';
import { ClipExtension } from '@deck.gl/extensions';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureDataCached(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.RasterLayer({
      // data properties
      image: image,
      bounds: [-180, -90, 180, 90],
      extensions: [new ClipExtension()],
      clipBounds: [-181, -85.051129, 181, 85.051129],
      // style properties
      palette: [
        [0, [255, 255, 255],
        [5, [127, 255, 255],
        [10, [127, 255, 127],
        [15, [255, 255, 127],
        [20, [255, 127, 127],
        [25, [127, 0, 0],
      ],
      pickable: true,
    }),
  ],
  onHover: event => console.log(event.raster),
});
```

### Data Properties

See [Data properties](/weatherlayers-gl/layers/data#data-properties) common for all layers.

### Style Properties

See [Style properties](/weatherlayers-gl/layers/style-properties) common for all layers.

#### `palette`

Type: color palette text or array, required

Palette used to interpolate values to colors.

Formats:

* text (`string`) - see [Text format](https://github.com/weatherlayers/cpt2js#text-format) for details
* array (`[number, PaletteColor][]`) - `PaletteColor` is any object accepted by [Chroma.js constructor](https://vis4.net/chromajs/#chroma)

#### `gridEnabled`

Type: boolean, optional

Default: `false`

Displays a grid of points to allow for verification how the rendered data aligns to the grid.

### Picking Info

Type: [`RasterPointProperties`](/weatherlayers-gl/types#rasterpointproperties)

If `pickable: true`, the picking info passed to callbacks (`onHover`, `onClick`, etc.) provides information on which pixel was picked. It contains an additional `raster` field.

Float32 data are recommended for the best precision.

See [Tooltip control](/weatherlayers-gl/controls/tooltip-control) and [BitmapLayer Pixel Picking](https://deck.gl/docs/api-reference/layers/bitmap-layer#pixel-picking).


# Contour Layer

Variable rendered as contours

### Example

![Contour Layer](/files/7ZoUdT91Xy2NiZ7Gmzkf)

```javascript
import { Deck } from '@deck.gl/core';
import { ClipExtension } from '@deck.gl/extensions';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureData(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.ContourLayer({
      id: 'contour',
      // data properties
      image: image,
      bounds: [-180, -90, 180, 90],
      // style properties
      interval: 200,
      extensions: [new ClipExtension()],
      clipBounds: [-181, -85.051129, 181, 85.051129],
    }),
  ],
});
```

### Data Properties

See [Data properties](/weatherlayers-gl/layers/data#data-properties) common for all layers.

### Style Properties

See [Style properties](/weatherlayers-gl/layers/style-properties) common for all layers.

#### `interval`

Type: number, required

Interval between contour lines in the data units. The greater interval, the less contour lines are rendered.

The value must be in the same units as the data image.

#### `majorInterval`

Type: number, optional

Default: `0` (every contour line is a major contour line)

Interval between major contour lines in the data units. The greater interval, the less major contour lines are rendered.

The value must be in the same units as the data image.

#### `width`

Type: `number`, optional

Default: `1`

Width of the contour line. See [LineLayer getWidth](https://deck.gl/docs/api-reference/layers/line-layer#getwidth).

Major contour lines are rendered with full width, minor contour lines are rendered with half width.

#### `color`

Type: color `[number, number, number, number?]`, optional

Default: `[255, 255, 255]`

Color of the contour line. See [LineLayer getColor](https://deck.gl/docs/api-reference/layers/line-layer#getcolor).

Major contour lines are rendered with full opacity, minor contour lines are rendered with half opacity.

#### `palette`

Type: color palette text or array, optional

Palette used to interpolate values to colors.

Formats:

* text (`string`) - see [Text format](https://github.com/weatherlayers/cpt2js#text-format) for details
* array (`[number, PaletteColor][]`) - `PaletteColor` is any object accepted by [Chroma.js constructor](https://vis4.net/chromajs/#chroma)


# HighLow Layer

Variable rendered as highs/lows

### Example

![HighLow Layer](/files/J0165HkqmarXppQ0r3ue)

```javascript
import { Deck } from '@deck.gl/core';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureData(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.HighLowLayer({
      id: 'highLow',
      // data properties
      image: image,
      bounds: [-180, -90, 180, 90],
      // style properties
      radius: 1000, // km
    }),
  ],
});
```

### Data Properties

See [Data properties](/weatherlayers-gl/layers/data#data-properties) common for all layers.

### Style Properties

See [Style properties](/weatherlayers-gl/layers/style-properties) common for all layers.

#### `radius`

Type: number, required

Radius in km to filter nearby values. The greater radius, the less values are detected.

#### `unitFormat`

Type: [`UnitFormat`](/weatherlayers-gl/types#unitformat), optional

Default: `null`

Unit definition to be used for formatting numbers.

#### `textFormatFunction`

Type: function `(value: number, unitFormat: UnitFormat) => string`, optional

Default: `(value, unitFormat) => unitFormat ? formatValue(value, unitFormat) : Math.round(value).toString()`

Function to format the value.

#### `textFontFamily`

Type: string, optional

Default: `"Helvetica Neue", Arial, Helvetica, sans-serif`

Font family of the text. See [TextLayer fontFamily](https://deck.gl/docs/api-reference/layers/text-layer#fontfamily).

#### `textSize`

Type: number, optional

Default: `12`

Size of the text. See [TextLayer getSize](https://deck.gl/docs/api-reference/layers/text-layer#getsize).

#### `textColor`

Type: color `[number, number, number, number?]`, optional

Default: `[255, 255, 255]`

Color of the text. See [TextLayer getColor](https://deck.gl/docs/api-reference/layers/text-layer#getcolor).

#### `textOutlineWidth`

Type: number, optional

Default: `1`

Width of outline around the text, relative to the font size. See [TextLayer outlineWidth](https://deck.gl/docs/api-reference/layers/text-layer#outlinewidth).

#### `textOutlineColor`

Type: color `[number, number, number, number?]`, optional

Default: `[13, 13, 13]`

Color of outline around the text. See [TextLayer outlineColor](https://deck.gl/docs/api-reference/layers/text-layer#outlinecolor).

#### `palette`

Type: color palette text or array, optional

Palette used to interpolate values to colors.

Formats:

* text (`string`) - see [Text format](https://github.com/weatherlayers/cpt2js#text-format) for details
* array (`[number, PaletteColor][]`) - `PaletteColor` is any object accepted by [Chroma.js constructor](https://vis4.net/chromajs/#chroma)


# Front Layer

Front data rendered as front lines with icons

### Example

![Front Layer - cold/warm/occluded weather fronts](/files/YLi7O2wr1GY4TlIvud36)

![Front Layer - stationary front](/files/ef13WvKnbVu12sOtSHDs)

```javascript
import { Deck } from '@deck.gl/core';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const frontData = [
  { type: WeatherLayers.FrontType.COLD, path: [...] },
  { type: WeatherLayers.FrontType.WARM, path: [...] },
  { type: WeatherLayers.FrontType.OCCLUDED, path: [...] },
  { type: WeatherLayers.FrontType.STATIONARY, path: [...] },
];

const deckgl = new Deck({
  layers: [
    new WeatherLayers.FrontLayer({
      id: 'front',
      // data properties
      data: frontData,
      // style properties
      getType: d => d.type,
      getPath: d => d.path,
      coldColor: [37, 99, 235], // Tailwind CSS blue-600
      warmColor: [220, 38, 38], // Tailwind CSS red-600
      occludedColor: [124, 58, 237], // Tailwind CSS violet-600
    }),
  ],
});
```

### Data Properties

#### `data`

Type: `DataT`

Array of data objects. See [Layer data](https://deck.gl/docs/api-reference/core/layer#data).

The data type can be any object. Specific fields should be accessed or mapped using accessors below

### Style Properties

#### `getType`

Type: `(d: DataT) => WeatherLayers.FrontType`

Accessor for the front type.

#### `getPath`

Type: `(d: DataT) => [number, number][]`

Accessor for the front path.

#### `width`

Type: `number`, optional

Default: 2

Width of the line. See [LineLayer getWidth](https://deck.gl/docs/api-reference/layers/line-layer#getwidth).

#### `coldColor`

Type: color `[number, number, number, number?]`, optional

Default: `[0, 0, 255]`

Color of the line and icon for cold fronts. See [LineLayer getColor](https://deck.gl/docs/api-reference/layers/line-layer#getcolor).

#### `warmColor`

Type: color `[number, number, number, number?]`, optional

Default: `[255, 0, 0]`

Color of the line and icon for warm fronts. See [LineLayer getColor](https://deck.gl/docs/api-reference/layers/line-layer#getcolor).

#### `occludedColor`

Type: color `[number, number, number, number?]`, optional

Default: `[148, 0, 211]`

Color of the line and icon for occluded fronts. See [LineLayer getColor](https://deck.gl/docs/api-reference/layers/line-layer#getcolor).


# Grid Layer

Variable rendered as grid of values or symbols (arrows, wind barbs)

### Example

![Grid Layer](/files/9dyAc25kN5miVEifboBW)

```javascript
import { Deck } from '@deck.gl/core';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureData(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.GridLayer({
      id: 'grid',
      // data properties
      image: image,
      bounds: [-180, -90, 180, 90],
    }),
  ],
});
```

### Example: Arrows

![Grid Layer: Arrows](/files/aeYxLZe9m3ZQjtsUONHH)

```javascript
import { Deck } from '@deck.gl/core';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureDataCached(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.GridLayer({
      // data properties
      image: image,
      imageType: WeatherLayers.ImageType.VECTOR,
      bounds: [-180, -90, 180, 90],
      
      // style properties
      style: WeatherLayers.GridStyle.ARROW,
      iconBounds: [0, 100],
    }),
  ],
});
```

### Example: Wind Barbs

![Grid Layer: Wind Barbs](/files/IHRGOi6fQGycRdwudYNF)

```javascript
import { Deck } from '@deck.gl/core';
import * as WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureDataCached(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.GridLayer({
      // data properties
      image: image,
      imageType: WeatherLayers.ImageType.VECTOR,
      bounds: [-180, -90, 180, 90],
      
      // style properties
      style: WeatherLayers.GridStyle.WIND_BARB,
      iconBounds: [0, 100 * 0.51444], // 100 kts to m/s
    }),
  ],
});
```

### Data Properties

See [Data properties](/weatherlayers-gl/layers/data#data-properties) common for all layers.

### Style Properties

See [Style properties](/weatherlayers-gl/layers/style-properties) common for all layers.

#### `style`

Type: enum `WeatherLayers.GridStyle`, values: `VALUE`, `ARROW`, `WIND_BARB`, optional

Default: `VALUE`

Style of the grid points, values or symbols.

If `style: ARROW` or `style: WIND_BARB`, `imageType` must be `VECTOR`.

#### `density`

Type: number, optional

Default: `0`

Grid point density. Recommended values are `-2`, `-1`, `0`, `1`, `2` (lowest to highest density). Larger values can cause performance issues.

#### `unitFormat`

Type: [`UnitFormat`](/weatherlayers-gl/types#unitformat), optional

Default: `null`

Unit definition to be used for formatting numbers.

#### `textFormatFunction`

Type: function `(value: number, unitFormat: UnitFormat) => string`, optional

Default: `(value, unitFormat) => unitFormat ? formatValue(value, unitFormat) : Math.round(value).toString()`

Function to format the value.

#### `textFontFamily`

Type: string, optional

Default: `"Helvetica Neue", Arial, Helvetica, sans-serif`

Font family of the text. See [TextLayer fontFamily](https://deck.gl/docs/api-reference/layers/text-layer#fontfamily).

#### `textSize`

Type: number, optional

Default: `12`

Size of the text. See [TextLayer getSize](https://deck.gl/docs/api-reference/layers/text-layer#getsize).

#### `textColor`

Type: color `[number, number, number, number?]`, optional

Default: `[255, 255, 255]`

Color of the text. See [TextLayer getColor](https://deck.gl/docs/api-reference/layers/text-layer#getcolor).

#### `textOutlineWidth`

Type: number, optional

Default: `1`

Width of outline around the text, relative to the font size. See [TextLayer outlineWidth](https://deck.gl/docs/api-reference/layers/text-layer#outlinewidth).

#### `textOutlineColor`

Type: color `[number, number, number, number?]`, optional

Default: `[13, 13, 13]`

Color of outline around the text. See [TextLayer outlineColor](https://deck.gl/docs/api-reference/layers/text-layer#outlinecolor).

#### `iconBounds`

Type: tuple of lower and upper bound `[number, number]`, required if `style: ARROW`

Default if `style: WIND_BARB`: `[0, 100 * 0.51444]` (100 knots to m/s, assumes the data units are m/s)

Bounds of the icon in the data units. The lower bound is usually 0, the upper bound is the largest value in the data units that matches the largest value of the icons.

If `style: WIND_BARB`, the upper bound must match 100 knots in the data units.

#### `iconSize`

Type: `[number, number] | number`, optional

Default: `12`

Size of the icon. See [IconLayer getSize](https://deck.gl/docs/api-reference/layers/icon-layer#getsize).

If an array is passed in, it's treated as minimal and maximal icon size. The actual icon size is scaled by the data value.

#### `iconColor`

Type: color `[number, number, number, number?]`, optional

Default: `[255, 255, 255]`

Color of the icon. See [IconLayer getColor](https://deck.gl/docs/api-reference/layers/icon-layer#getcolor).

#### `palette`

Type: color palette text or array, optional

Palette used to interpolate values to colors.

Formats:

* text (`string`) - see [Text format](https://github.com/weatherlayers/cpt2js#text-format) for details
* array (`[number, PaletteColor][]`) - `PaletteColor` is any object accepted by [Chroma.js constructor](https://vis4.net/chromajs/#chroma)


# Data Loading

### Example - supported file formats

```javascript
import { Deck } from '@deck.gl/core';
import WeatherLayers from 'weatherlayers-gl';

// load data
const image = await WeatherLayers.loadTextureData(url);

const deckgl = new Deck({
  layers: [
    new WeatherLayers.XxxLayer({
      image: image,
    }),
  ],
});
```

### Example 2 - custom file formats

```javascript
import { Deck } from '@deck.gl/core';
import WeatherLayers from 'weatherlayers-gl';

// load data
const image = { data: new Float32Array(...), width: ..., height: ... };

const deckgl = new Deck({
  layers: [
    new WeatherLayers.XxxLayer({
      image: image,
    }),
  ],
});
```


# Data Properties

Data properties common for all layers.

#### `image`

Type: [`TextureData`](/weatherlayers-gl/types#texturedata), required

Data type can be either Uint8 (`Uint8Array`, `Uint8ClampedArray`) or Float32 (`Float32Array`).

Data length must be `width * height * bandsCount`.

Supported bands count is `1`, `2` or `4`. See `imageType` and [Data Sources](/weatherlayers-gl/data-sources).

For multi-band data, the expected format is that the band values are interleaved by pixel. For example, for vector data with `u`, `v` values, the expected format is `[u1, v1, u2, v2, ...]`. This is also known as [BIP format](https://desktop.arcgis.com/en/arcmap/latest/manage-data/raster-and-images/bip-format-example.htm).

This is the format expected by the library, after decoding the image from the original file format. Decode the original file format either with [`loadTextureData`](/weatherlayers-gl/functions#loadtexturedata-url-string-cache-map-less-than-string-any-greater-than-or-false-default_cache-promis) or yourself.

![Band interleaved by pixel (Source: ArcGIS Documentation)](/files/sCkbzhUClaaMEz7tQ2pn)

#### `image2`

Type: [`TextureData`](/weatherlayers-gl/types#texturedata), optional

The subsequent data image. Used if `imageWeight > 0`.

See `image` for details.

#### `imageSmoothing`

Type: number, optional

Default: `0` (no smoothing)

Smoothing applied to the data. Increasing the smoothing is useful in case of rendering artifacts with low resolution data or if high detail is undesired. Maximal smoothing is unlimited.

#### `imageInterpolation`

Type: [`ImageInterpolation`](/weatherlayers-gl/types#imageinterpolation), values: `NEAREST`, `LINEAR`, `CUBIC`, optional

Default: `CUBIC`

`NEAREST` disables any interpolation, renders the data for a particular lng/lat location from the nearest available pixel. Raster layer is pixelizated.

`LINEAR` interpolates the data for a particular lng/lat location from four pixels using a linear interpolation. Provides a balance between smoothness and performance.

`CUBIC` interpolates the data for a particular lng/lat location from sixteen pixels using a cubic interpolation. Provides the best smoothness. Required for Contour layer with byte data format.

#### `imageWeight`

Type: number `0-1`, optional

Default: `0`

Interpolation weight between `image` and `image2`.

#### `imageType`

Type: [`ImageType`](/weatherlayers-gl/types#imagetype), values: `SCALAR`, `VECTOR`, optional

Default: `SCALAR` (for layers that support both scalar and vector data), `VECTOR` (for layers that support vector data only)

Image type, scalar or vector.

#### `imageUnscale`

Type: [`ImageUnscale`](/weatherlayers-gl/types#imageunscale), optional

Default: `null` (no unscaling)

Original data value bounds, used to unscale the data if the original data are scaled (quantized).

Supported if the data type is Uint8.

#### `imageMinValue`

Type: number, optional

Default: `null` (no limit)

Minimal value limit to render the data.

The value must be in the same units as the data image.

#### `imageMaxValue`

Type: number, optional

Default: `null` (no limit)

Maximal value limit to render the data.

The value must be in the same units as the data image.

#### `bounds`

Type: bounding box of minX, minY, maxX, maxY `[number, number, number, number]`, required

Original data bounding box.

Recommended value is `[-180, -90, 180, 90]` for a global image.

#### `minZoom`

Type: number `0-20`, optional

Default: `null` (no limit)

Minimal zoom limit to render the layer.

#### `maxZoom`

Type: number `0-20`, optional

Default: `10` (ContourLayer), `15` (ParticleLayer), `null` (other layers, no limit)

Maximal zoom limit to render the layer.

It's possible to override a lower default value to a higher value, but rendering artifacts may occur in high zoom levels due to a low precision.


# Style Properties

Style properties common for all layers.

#### `visible`

Type: boolean, optional

Default: true

Visibility of the layer. See [Layer visible](https://deck.gl/docs/api-reference/core/layer#visible).

#### `opacity`

Type: number, optional

Default: `1`

Opacity of the layer. See [Layer opacity](https://deck.gl/docs/api-reference/core/layer#opacity).

#### `extensions`

Type: array of extensions

Use `[new ClipExtension()]` for a global image in an equirectangular projection on a [WebMercatorViewport](https://deck.gl/docs/api-reference/core/web-mercator-viewport), to clip the areas of the image beyond a valid Mercator bounding box. See [ClipExtension](https://deck.gl/docs/api-reference/extensions/clip-extension).

#### `clipBounds`

Type: bounding box of minX, minY, maxX, maxY `[number, number, number, number]`, required for `ClipExtension`

Recommended value is `[-181, -85.051129, 181, 85.051129]` for a global image in an equirectangular projection on a [WebMercatorViewport](https://deck.gl/docs/api-reference/core/web-mercator-viewport), to clip the areas of the image beyond a valid Mercator bounding box. There is `181` instead of `180` to avoid a pixel gap at the antimeridian. See [ClipExtension.clipBounds](https://deck.gl/docs/api-reference/extensions/clip-extension#clipbounds).


# Controls

Sample controls for quick integration. Use as-is, or as a reference for implementing your own custom controls.


# Legend Control

Legend control shows the color legend for the raster layer

### Example

![Legend Control](/files/1soNoELHEBlLnUWfcWE2)

```javascript
import * as WeatherLayers from 'weatherlayers-gl';

const legendControl = new WeatherLayers.LegendControl({
  title: 'Wind',
  unitFormat: {
    unit: 'm/s',
  },
  palette: [
    [0, [255, 255, 255]],
    [5, [127, 255, 255]],
    [10, [127, 255, 127]],
    [15, [255, 255, 127]],
    [20, [255, 127, 127]],
    [25, [127, 0, 0]],
  ],
});
legendControl.addTo(document.getElementById('controls'));
```

### Constructor

#### `LegendControl(config: LegendConfig = {})`

### Config Properties

#### `width`

Type: number, optional

Default: 300

Width of the control.

#### `ticksCount`

Type: number, optional

Default: 6

Ticks to be displayed.

#### `title`

Type: string, required

Title to be displayed.

#### `unitFormat`

Type: [`UnitFormat`](/weatherlayers-gl/types#unitformat), required

Unit definition to be used for formatting numbers.

#### `palette`

Type: color palette text or array, required

Palette used to interpolate values to colors.

Formats:

* text (`string`) - see [Text format](https://github.com/weatherlayers/cpt2js#text-format) for details
* array (`[number, PaletteColor][]`) - `PaletteColor` is any object accepted by [Chroma.js constructor](https://vis4.net/chromajs/#chroma)

### Methods

See [Control](/weatherlayers-gl/controls/control) for common Control methods.


# Timeline Control

Timeline control allows playing datetimes as animation with linear interpolation between two subsequent datetimes

### Example

![Timeline Control](/files/43j6o6fQe8Mw93WsObhf)

<pre class="language-javascript"><code class="lang-javascript">import * as WeatherLayers from 'weatherlayers-gl';

const files = [
  { datetime: '2021-09-01T20:00:00Z',  url: '...' },
  { datetime: '2021-09-01T21:00:00Z',  url: '...' },
  { datetime: '2021-09-01T22:00:00Z',  url: '...' },
];
const datetimes = files.map(file => file.datetime);
let currentDatetime = datetimes[0];
const timelineControl = new WeatherLayers.TimelineControl({
  datetimes: datetimes,
  datetime: currentDatetime,
  onPreload: datetimes => {
    // preload requested data
    return Promise.all(datetimes.map(datetime => {
      return WeatherLayers.loadTextureData(files.find(file => file.datetime === datetime).url);
    });
  },
  onUpdate: datetime => {
    // update displayed data
    currentDatetime = datetime;
    update();
  },
});
timelineControl.addTo(document.getElementById('controls'));

async function update() {
  const startDatetime = WeatherLayers.getClosestStartDatetime(datetimes, currentDatetime);
  const endDatetime = WeatherLayers.getClosestEndDatetime(datetimes, currentDatetime);
  const imageWeight = WeatherLayers.getDatetimeWeight(startDatetime, endDatetime, currentDatetime);
<strong>  const image = await WeatherLayers.loadTextureData(files.find(file => file.datetime === startDatetime).url);
</strong>  const image2 = await WeatherLayers.loadTextureData(files.find(file => file.datetime === endDatetime).url);
  
  // update layers
  deckgl.setProps({
    layers: [
      new WeatherLayers.XxxLayer({
        image: image,
        image2: image2,
        imageWeight: imageWeight,
      }),
    ],
  });
}
update();
</code></pre>

### Constructor

#### `TimelineControl(config: TimelineConfig = {})`

### Config Properties

#### `width`

Type: number, optional

Default: 300

Width of the control.

#### `datetimes`

Type: [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`[]`, required

Datetimes to be displayed in the timeline.

#### `datetimeInterpolate`

Type: boolean, optional

Default: true

#### `datetime`

Type: [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring), required

Current datetime selected in the timeline.

#### `onPreload`

Type: `(datetimes:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`[]) => Promise<void>[] | Promise<void>`, optional

Preload callback, use for preloading requested data.

If an array of promises is returned, the progress is displayed in the loader text.

#### `onUpdate`

Type: `(datetime:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`) => void`, optional

Update callback, use for updating displayed data.

#### `fps`

Type: number, optional

Default: 15

Timeline animation speed, in frames per seconds. Lower number is slower animation, higher number is faster animation.

### Methods

See [Control](/weatherlayers-gl/controls/control) for common Control methods.

#### `toggle(running?: boolean): Promise<void>`

Toggles (starts or pauses) the timeline animation.

Before starting, it calls and awaits `onPreload` with all datetimes.

#### `start(): Promise<void>`

Starts the timeline animation.

Before starting, it calls and awaits `onPreload` with all datetimes.

#### `pause(): void`

Pauses the timeline animation.

#### `stop(): void`

Stops (pauses and resets) the timeline animation.

#### `reset(): void`

Resets the timeline animation.

#### `stepBackward(): Promise<void>`

Steps backward in the timeline animation.

Before stepping, it calls and awaits `onPreload` with datetimes required to display the requested step.

#### `stepForward(): Promise<void>`

Steps forward in the timeline animation.

Before stepping, it calls and awaits `onPreload` with datetimes required to display the requested step.


# Tooltip Control

Tooltip control shows the value (and the direction for vector datasets) at current mouse position on hovering the raster layer

### Example

![Tooltip Control](/files/TNaXGQKpleuFKOPvGR1N)

```javascript
import * as WeatherLayers from 'weatherlayers-gl';

const tooltipControl = new WeatherLayers.TooltipControl({
  unitFormat: {
    unit: 'm/s',
  },
  directionFormat: WeatherLayers.DirectionFormat.CARDINAL3,
  followCursor: true,
});
tooltipControl.addTo(deckgl.getCanvas().parentElement);
deckgl.setProps({ onHover: event => tooltipControl.updatePickingInfo(event) });
```

### Constructor

#### `TooltipControl(config: TooltipConfig = {})`

### Config Properties

#### `unitFormat`

Type: [`UnitFormat`](/weatherlayers-gl/types#unitformat), required

Unit definition to be used for formatting.

#### `directionType`

Type: [`DirectionType`](/weatherlayers-gl/types#directiontype), optional

Default value: `INWARD`

Direction type to be used for formatting.

#### `directionFormat`

Type: [`DirectionFormat`](/weatherlayers-gl/types#directionformat), optional

Default value: `VALUE`

Direction format to be used for formatting.

#### `followCursor`

Type: boolean, optional

Default value: false

Follow the mouse cursor position.

#### `followCursorOffset`

Type: number, optional

Default value: `16`

Offset from the mouse cursor position.

#### `followCursorPlacement`

Type: [`Placement`](/weatherlayers-gl/types#placement), optional

Default value: `BOTTOM`

Placement from the mouse cursor position.

### Methods

See [Control](/weatherlayers-gl/controls/control) for common Control methods.

#### `update(rasterPointProperties:` [`RasterPointProperties`](/weatherlayers-gl/types#rasterpointproperties) `| undefined): void`

Updates the tooltip displayed with the given `rasterPointProperties` or hides the tooltip.

#### `updatePickingInfo(pickingInfo: PickingInfo & { raster?:` [`RasterPointProperties`](/weatherlayers-gl/types#rasterpointproperties) `}): void`

Updates the tooltip displayed with the given `pickingInfo` or hides the tooltip.


# Attribution Control

Attribution control shows the attribution for the data producer

### Example

![Attribution Control](/files/UqsQUak5ULtsHW5rDsUH)

```javascript
import * as WeatherLayers from 'weatherlayers-gl';

const attributionControl = new WeatherLayers.AttributionControl({
  attribution: 'NOAA / GFS via WeatherLayers',
});
attributionControl.addTo(document.getElementById('controls'));
```

### Constructor

#### `AttributionControl(config: AttributionConfig = {})`

### Config Properties

#### `attribution`

Type: string, required

Attribution to be displayed.

### Methods

See [Control](/weatherlayers-gl/controls/control) for common Control methods.


# Logo Control

Logo control shows WeatherLayers logo

### Example

![Logo Control](/files/GtL7xofKDV9a93kcr5Tx)

```javascript
import * as WeatherLayers from 'weatherlayers-gl';

const logoControl = new WeatherLayers.LogoControl();
logoControl.addTo(document.getElementById('controls'));
```

### Constructor

#### `LogoControl(config: LogoConfig = {})`

### Methods

See [Control](/weatherlayers-gl/controls/control) for common Control methods.


# Control

Parent control

### Constructor

#### `Control(config: ControlConfig = {})`

### Methods

#### `addTo(target: HTMLElement): void`

Appends the control to the DOM as a child of the given `target`.

#### `prependTo(target: HTMLElement): void`

Prepends the control to the DOM as a child of the given `target`.

#### `remove(): void`

Removes the control from the DOM.

#### `setConfig(config: ControlConfig): void`

Updates the control config.


# Types

### Image Types

#### `ImageInterpolation`

```typescript
enum ImageInterpolation {
  NEAREST = 'NEAREST',
  LINEAR = 'LINEAR',
  CUBIC = 'CUBIC',
}
```

Image interpolation method.

* `NEAREST` - no interpolation, fastest
* `LINEAR` - medium interpolation quality
* `CUBIC` - best interpolation quality, slowest

#### `ImageType`

```typescript
enum ImageType {
  SCALAR = 'SCALAR',
  VECTOR = 'VECTOR',
}
```

Image type.

* `SCALAR` - contains a single variable
* `VECTOR` - contains two variables, `u` and `v` vector components

#### `ImageUnscale`

```typescript
type ImageUnscale = [min: number, max: number] | null;
```

Value bounds to unscale image data to original data, or null if image contains original data already and no unscaling is needed.

#### `ImageProperties`

```typescript
interface ImageProperties {
  image: TextureData;
  image2: TextureData | null;
  imageSmoothing: number;
  imageInterpolation: ImageInterpolation;
  imageWeight: number;
  imageType: ImageType;
  imageUnscale: ImageUnscale;
  imageMinValue: number | null;
  imageMaxValue: number | null;
}
```

Properties to render a single image.

#### `DirectionType`

```typescript
enum DirectionType {
  INWARD = 'INWARD',
  OUTWARD = 'OUTWARD',
}
```

Direction type to be used for formatting.

* `INWARD` - formats direction inwards from outside to the current point
  * meteorological - wind, waves
* `OUTWARD` - formats direction outwards from the current point to outside
  * climatological data - currents

#### `DirectionFormat`

```typescript
enum DirectionFormat {
  VALUE = 'VALUE',
  CARDINAL = 'CARDINAL',
  CARDINAL2 = 'CARDINAL2',
  CARDINAL3 = 'CARDINAL3',
}
```

Direction format to be used for formatting.

* `VALUE` - formats direction as a value in degrees
* `CARDINAL` - formats direction as a 1-letter cardinal (4 possible values)
  * N, E, S, W
* `CARDINAL2` - formats direction as a 2-letter cardinal (8 possible values)
  * N, NE, E, SE, S, SW, W, NW
* `CARDINAL3` - formats direction as a 3-letter cardinal (16 possible values)
  * N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW

<img src="/files/gmOT8MK8zsQn8wRnWSV5" alt="Compass Rose (Source: Wikipedia)" width="563">

#### `Placement`

```typescript
enum Placement {
  BOTTOM = 'BOTTOM',
  TOP = 'TOP',
  RIGHT = 'RIGHT',
  LEFT = 'LEFT',
}
```

Tooltip control placement from the mouse cursor position.

### Load Types

#### `TextureData`

```typescript
interface TextureData {
  data: Uint8Array | Uint8ClampedArray | Float32Array;
  width: number;
  height: number;
}
```

Texture data to be used as input to raster rendering layers.

#### `UnitFormat`

```typescript
interface UnitFormat {
  unit: string;
  scale?: number;
  offset?: number;
  decimals?: number;
}
```

Format definition to be used for formatting raw values with units.

#### `RasterPointProperties`

```typescript
interface RasterPointProperties {
  value: number;
  direction?: number;
}
```

Raster point properties for a particular position.

### Datetime Types

#### `DatetimeISOString`

```typescript
type DatetimeISOString = string;
```

Valid ISO 8601 datetime.

#### `DatetimeISOStringRange`

```typescript
type DatetimeISOStringRange = [start: DatetimeISOString, end: DatetimeISOString];
```

Valid ISO 8601 datetime range.

#### `OpenDatetimeISOStringRange`

```typescript
type OpenDatetimeISOStringRange = [start: DatetimeISOString | null, end: DatetimeISOString | null];
```

Valid ISO 8601 datetime range. Null start/end represent an open end.

#### `DurationISOString`

```typescript
type DurationISOString = string;
```

Valid ISO 8601 duration.


# Functions

### Library Functions

#### `setLibrary<T>(name: string, library: T): void`

Sets an optional dependency.

By default, optional dependencies are loaded with a dynamic import. If the dynamic import is not supported by your environment, use this function to set the optional dependency explicitly.

### Load Functions

#### `loadTextureData(url: string, options?: CachedLoadOptions<TextureData>): Promise<`[`TextureData`](/weatherlayers-gl/types#texturedata)`>`

Loads the url as texture data. The url should be PNG, WebP or GeoTIFF image.

GeoTIFF requires [geotiff.js ](https://github.com/geotiffjs/geotiff.js/)as an optional dependency if loading GeoTIFF images.

Use in `image`/`image2` property.

#### `loadJson(url: string, options?: CachedLoadOptions<any>): Promise<any>`

Loads the url as JSON. The response should be a JSON file.

#### `LoadOptions`

```typescript
interface LoadOptions {
  headers?: Record<string, string>;
  signal?: AbortSignal;
}
```

Data request load options.

* `headers` - custom HTTP headers
* `signal` - abort signal for cancelling the request

#### `CachedLoadOptions`

```typescript
interface CachedLoadOptions<T> extends LoadOptions {
  cache?: Map<string, T | Promise<T>> | false;
}
```

The response is cached to the given cache, or to the default global cache, or caching can be disabled by `false`.

### Datetime Functions

#### `getClosestStartDatetime(datetimes:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`[], datetime:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`):` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring) `| undefined`

Gets the closest start datetime (i.e. lower or equal) for the given datetime from the given datetimes.

Use to find the correct start image to load, to be used in `image` property.

#### `getClosestEndDatetime(datetimes:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`[], datetime:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`):` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring) `| undefined`

Gets the closest end datetime (i.e. greater or equal) for the given datetime from the given datetimes.

Use to find the correct end image to load, to be used in `image2` property. Applicable only if `datetimeInterpolate` is enabled.

#### `getDatetimeWeight(startDatetime:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`, endDatetime:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`, datetime:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`): number`

Gets the datetime weight between the given start and end datetime for the given datetime. The returned value is a number `0-1`.

Use in `imageWeight` property. Applicable only if `datetimeInterpolate` is enabled.

#### `offsetDatetime(datetime:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`, hour: number):` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)

Adds hours to the given datetime.

#### `offsetDatetimeRange(datetime:` [`DatetimeISOString`](/weatherlayers-gl/types#datetimeisostring)`, startHour: number, endHour: number):` [`DatetimeISOStringRange`](/weatherlayers-gl/types#datetimeisostringrange)

Adds start hour and end hour to the given datetime. The returned value is a datetime range.

### Raster functions

#### `getRasterPoints(imageProperties:` [`ImageProperties`](/weatherlayers-gl/types#imageproperties)`, bounds: GeoJSON.BBox, positions: GeoJSON.Position[]): GeoJSON.FeatureCollection<GeoJSON.Point,` [`RasterPointProperties`](/weatherlayers-gl/types#rasterpointproperties)`>`

Gets raster points for the given positions.


# Data Sources

WeatherLayers GL can be used either with custom self-hosted data or with WeatherLayers Cloud.

For integrating any custom data (NetCDF, GRIB), the data needs to be transformed by your backend server to a supported data type, data format and map projection.

### Data sources

* [WeatherLayers Cloud](/weatherlayers-cloud) public data sources - NOAA (GFS, GFS Wave), Copernicus (CMEMS, CAMS)
* other public data sources - ECMWF, ICON, Copernicus (ERA5), ...
* commercial data sources
* custom data sources - your own data from scientific research

### Supported data types

* Uint8
  * quantized data into 256 possible values
  * lower precision, higher compression ratio for lower file size
  * recommended for visualization purposes
  * original data bounds need to be provided to unscale the data into the original data, see [Data Properties imageUnscale](/weatherlayers-gl/layers/data-properties#imageunscale)
* Float32
  * original data
  * better precision, lower compression ratio and larger file size
  * recommended for scientific purposes, or for use cases where exact values with no quantization errors are needed

### Supported data formats

* PNG, WebP (Uint8)
  * scalar - R channel
    * nodata - `0` in A channel
  * vector - RG channels
    * nodata - `0` in A channel
* GeoTIFF (Uint8)
  * scalar - band 1
    * nodata - `0` in band 2
  * vector - bands 1 and 2
    * nodata - `0` in band 4
* GeoTIFF (Float32)
  * scalar - band 1
    * nodata - `NaN` in band 1
  * vector - bands 1 and 2
    * nodata - `NaN` in bands 1 and 2

### Supported projections

* equirectangular projection (EPSG:4326)

### Data transformation

Data transformation into a supported format can be done on your servers with GDAL.

See [gdal\_translate](https://gdal.org/programs/gdal_translate.html) for transformations between data types and data formats.

See [gdalwarp](https://gdal.org/programs/gdalwarp.html) for transformations between map projections.

See [gdal\_calc](https://gdal.org/en/stable/programs/gdal_calc.html) for calculations and [gdalbuildvrt](https://gdal.org/en/stable/programs/gdalbuildvrt.html) for merging files.

### Example – Temperature from GRIB to PNG

Scale from \[213.15, 325.15] to \[0, 255], disable GDAL unit normalization from K to C:

{% code overflow="wrap" %}

```sh
gdal_translate -ot Byte -scale 213.15 325.15 0 255 --config GRIB_NORMALIZE_UNITS=NO temperature.grib temperature.png
```

{% endcode %}

WeatherLayers GL configuration:

* `imageType: WeatherLayers.ImageType.SCALAR`
* `imageUnscale: [213.15, 325.15]`

### Example – Wind from GRIB to PNG

Merge U and V files:

* R channel: U variable
* G channel: V variable
* B channel: anything, it's ignored, duplicating V variable is the easiest with GDAL, otherwise it would need a new separately created dataset with zeroes

{% code overflow="wrap" %}

```sh
gdalbuildvrt -separate wind.vrt wind_u.grib wind_v.grib wind_v.grib
```

{% endcode %}

Scale from \[-128, 127] to \[0, 255]:

{% code overflow="wrap" %}

```sh
gdal_translate -ot Byte -scale -128 127 0 255 wind.vrt wind.png
```

{% endcode %}

WeatherLayers GL configuration:

* `imageType: WeatherLayers.ImageType.VECTOR`
* `imageUnscale: [-128, 127]`


# Security

### Content Security Policy (CSP)

#### script-src

`blob:` - used by WebWorkers

#### style-src

`'unsafe-inline'` - used by Controls

#### img-src

`data:` - used by Legend Control and Grid Layer / Front Layer

`blob:` - used by loadTextureData with custom headers or abort signal


# Troubleshooting

### deck.gl shader hooks are not resolved

#### Issue

deck.gl must be used from a single bundle, otherwise it fails to resolve its shader hooks `DECKGL_FILTER_SIZE`, `DECKGL_FILTER_GL_POSITION`, `DECKGL_FILTER_COLOR`.

The shader source code calls these hooks but it's missing their declaration.

#### Symptoms

No layer displays. "Vertex shader is not compiled" error is logged in the browser console.

#### Solution

Check for duplicate deck.gl bundles used (versions or ESM vs CJS). Ensure that a single deck.gl bundle is used.

### Layers can't be enabled after disabling in MapLibre/Mapbox interleaved mode

#### Issue

Layers can't be reused, they need to be recreated.

#### Symptoms

After `deck.MapboxOverlay` is added to the map with `maplibregl.Map.addControl` and removed from the map with `maplibregl.Map.removeControl`, adding it back again with `maplibregl.Map.addControl` doesn't render any layers.

#### Solution

After removing `deck.MapboxOverlay` from the map with `maplibregl.Map.removeControl`, remove layers as well with `deck.MapboxOverlay.setProps({ layers: [] })`.

After adding `deck.MapboxOverlay` to the map with `maplibregl.Map.addControl`, add layers with `deck.MapboxOverlay.setProps({ layers: [...all layers...] })`.

### HighLowLayer doesn't display in MapLibre/Mapbox interleaved mode

#### Issue

HighLowLayer uses deck.gl CollisionFilterExtension, which can't be used after bitmap layers (RasterLayer, ContourLayer) in deck.gl <9.2.6. <https://github.com/visgl/deck.gl/issues/7864>

#### Symptoms

HighLowLayer doesn't display.

#### Solution

Upgrade to deck.gl 9.2.6+ and set `_renderLayersInGroups: true` in `MapboxOverlay` .

Previous workaround: Move HighLowLayer to be before bitmap layers (RasterLayer, ContourLayer), and offset it with `getPolygonOffset: () => [0, -1000]`.


# Pricing

Package and source code is dual-licensed, the choice of license is MPL-2.0 or our [License Terms of Use](https://weatherlayers.com/license-terms-of-use.html). Contact <support@weatherlayers.com> for details.


# Changelog

### 2026.5.2

*May 24th, 2026*

Bug fixes:

* Round numParticles to a multiple of 4, to improve compatibility with strict GPUs

### 2026.5.1

*May 11th, 2026*

Bug fixes:

* Fix "Binding bitmapTexture not set: Not found in shader layout" warning

### 2026.5.0

*May 10th, 2026*

Peer dependencies:

* **⚠️ Upgrade to deck.gl 9.3.2**

### 2026.2.0

*February 1st, 2026*

Minor changes:

* Use \_renderLayersInGroups for Maplibre/Mapbox interleaved demo
* Improve HighLow layer performance
  * Use filterSubLayer for minZoom/maxZoom, to avoid using shouldUpdateState with changeFlags.viewportChanged

Peer dependencies:

* Upgrade to deck.gl 9.2.6
* Upgrade to geotiff.js 3.0.0

### 2025.12.0

*December 11th, 2025*

Bug fixes:

* Fix "bytesPerRow must be a multiple of bytesPerPixel for rgba8unorm" error
  * <https://github.com/weatherlayers/weatherlayers-gl/issues/24>

Peer dependencies:

* Upgrade to deck.gl 9.2.5

### 2025.11.0

*November 16th, 2025*

New features:

* Add support for loading data with abort signal
  * This loads data with `fetch` as a blob instead of as an image
* Add `borderEnabled`, `borderWidth`, `borderColor`, `gridEnabled`, `gridSize`, `gridColor` to Raster layer

Peer dependencies:

* **⚠️ Upgrade to deck.gl 9.2.0**

### 2025.8.0

*August 8th, 2025*

Bug fixes:

* Fix CJS bundler error by updating transitive dependencies (cpt2js, geodesy-fn) to export dist files with .cjs file extension while keeping ESM default

### 2025.7.2

*July 13th, 2025*

Bug fixes:

* Fix "Image can't be decoded" error by avoiding multiple parallel decodes to hit a memory limit
  * <https://issues.chromium.org/issues/40676514>
* Fix loading GridLayer icons in an insecure context by using the loaded URL as a cache key directly instead of hashing it

### 2025.7.1

*July 6th, 2025*

Bug fixes:

* Fix Grid layer occasionally not displaying interpolated points due to floating-point calculation precision loss

### 2025.7.0

*July 4th, 2025*

Bug fixes:

* Fix bundler error "Module not found: Error: Default condition should be last one" by adding a default package export
* Fix runtime error "TypeError: Cannot read private member from an object whose class did not declare it" by improving compatibility with HMR proxies by using TS private fields instead of ESM private fields
* Fix Particle layer warning "Ignoring buffer for unknown attribute"

### 2025.6.1

*June 7th, 2025*

Bug fixes:

* Wait for image to be loaded before decoding

### 2025.6.0

*June 1st, 2025*

New features:

* Add `gridEnabled` to Raster layer
* Add support for loading data with custom HTTP headers
  * ⚠️ Use an options object as the second argument in `loadTextureData`
  * This loads data with `fetch` as a blob instead of as an image

Bug fixes:

* Fix grid offset for local images

### 2025.5.1

*May 18th, 2025*

Bug fixes:

* Add rollup-plugin-worker-factory to dependencies to avoid a strict bundler error

### 2025.5.0

*May 4th, 2025*

Bug fixes:

* Drop particles by position instead of color, fixes drop detection on Android

### 2025.3.0

*March 3rd, 2025*

New features:

* **⚠️ Open-source, dual-license with MPL**

Minor changes:

* Remove license file check and watermark
* Remove `setLicense` function
* Stop bundling dependencies

Bug fixes:

* Reorder exports by priority, fixes warning with Vite 6

### 2025.1.0

*January 26nd, 2025*

New features:

* Support for MapLibre globe projection
  * Requires MapLibre >= 5.0.0. See <https://github.com/maplibre/maplibre-gl-js/releases/tag/v5.0.0>

Bug fixes:

* Uniform grid point density in all latitudes in globe projection
* Uniform particle speed in all latitudes in globe projection

Peer dependencies:

* **⚠️ Upgrade to deck.gl 9.1.0**

### 2024.9.1

*September 28nd, 2024*

Minor changes:

* Replace uniforms with Uniform Buffer Objects as preparation for deck.gl 9.1
* Repeat the texture for global data, clamp the texture for regional data

### 2024.9.0

*September 22nd, 2024*

Bug fixes:

* Fix nodata detection for float inaccuracy in alpha channel

### 2024.8.2

*August 23rd, 2024*

Bug fixes:

* &#x20;**⚠️ Fix `The provided float value is non-finite.` error in Chrome 128**
  * Versions since 2024.2.0 are affected

### 2024.8.1

*August 20th, 2024*

Minor changes:

* Replace TS enums with string constants for cross-bundle compatibility between `weatherlayers-gl` and `weatherlayers-gl/client`
  * <https://www.totaltypescript.com/books/total-typescript-essentials/deriving-types#using-as-const-for-javascript-style-enums>

### 2024.8.0

*August 11th, 2024*

Minor changes:

* Split `UnitDefinition` interface (with `UnitSystem`) from `UnitFormat` interface (without `UnitSystem`)

Bug fixes:

* Fix basemap flickering during basemap zoom/pan interaction due to ParticleLayer animation in React

Peer dependencies:

* Upgrade to deck.gl 9.0.27

### 2024.7.0

*July 20, 2024*

New features:

* Display progress in Timeline control loader text

Bug fixes:

* Fix HighLow and Grid layer to not calculate points when disabled

### 2024.6.2

*July 2, 2024*

Bug fixes:

* Import optional dependencies with a static import instead of a dynamic import, to prevent Webpack warning "Critical dependency: the request of a dependency is an expression"

### 2024.6.1

*July 1, 2024*

Bug fixes:

* Fix corrupted build (internal dependencies missing in the bundle by mistake)

### 2024.6.0

*June 30, 2024*

Bug fixes:

* Add setLibrary function to set optional dependencies environments which don't support dynamic import
* Make geotiff dependency to be truly optional

Peer dependencies:

* Upgrade to deck.gl 9.0.20

### 2024.5.2

*May 27, 2024*

Minor features:

* Support loading images as data URIs

Bug fixes:

* Remove required `data:` protocol from CSP content-src by loading iconAtlas as images
* Fix LegendControl, TimelineControl interfaces

Peer dependencies:

* Upgrade to deck.gl 9.0.16

### 2024.5.1

*May 11, 2024*

Bug fixes:

* Fix updating Front layer data
* Remove reference to missing sourcemaps

### 2024.5.0

*May 9, 2024*

Bug fixes:

* Fix support for Angular by downgrading to ES2016 target in WebWorkers\
  <https://github.com/angular/angular-cli/issues/22191>

### 2024.4.3

*April 28, 2024*

Bug fixes:

* Fix Particle layer in Safari

Peer dependencies:

* Set geotiff.js as optional

### 2024.4.2

*April 15, 2024*

Bug fixes:

* Fix palette rendering

### 2024.4.1

*April 14, 2024*

Bug fixes:

* Fix basemap flickering during basemap zoom/pan interaction due to ParticleLayer animation in MapLibre/Mapbox interleaved mode
* Fix missing exported TS typings
* Disable unused mipmaps

Peer dependencies:

* Upgrade to deck.gl 9.0.7

### 2024.4.0

*April 3, 2024*

Peer dependencies:

* **⚠️ Upgrade to deck.gl 9.0.4**
  * This drops support for WebGL1 in favour of WebGL2. See <https://deck.gl/docs/whats-new> and <https://deck.gl/docs/upgrade-guide> for upgrading.
  * MapLibre: requires MapLibre >= 3.0.0 if using MapLibre with deck.gl interleaved to support WebGL2. See <https://github.com/maplibre/maplibre-gl-js/releases/tag/v3.0.0>
  * Mapbox: requires Mapbox >= 3.0.0 if using Mapbox with deck.gl interleaved to support WebGL2. See <https://github.com/mapbox/mapbox-gl-js/releases/tag/v3.0.0>
* Update geotiff.js to 2.1.3

### 2024.3.1

*March 29, 2024*

Bug fixes:

* Fix accepting custom `iconBounds` for wind barbs in Grid layer

### 2024.3.0

*March 24, 2024*

New features:

* Add `directionOrigin`, `followCursorOffset`, `followCursorPlacement` to Tooltip control

Minor changes:

* Slow down particles in higher latitudes to make the particle speed constant, generate more particles in higher latitudes to keep the particle density uniform

Bug fixes:

* Fix detecting NaN in Float data, so that they are ignored for rendering

### 2024.2.3

*February 13, 2024*

Minor changes:

* Allow array in `iconSize`, merge `iconSize` and `iconMinSize` in Grid layer
  * ⚠️ Use an array value in `iconSize` instead of `iconMinSize`

### 2024.2.2

*February 12, 2024*

New features:

* Add `iconMinSize` to Grid layer, enables smooth scaled icon sizes
  * ⚠️ Set `iconMinSize` for the original behavior of scaled icon sizes by values

Bug fixes:

* Fix refreshing Grid and HighLow layer properties

### 2024.2.1

*February 8, 2024*

New features:

* Add `majorInterval` to Contour layer
  * ⚠️ Set `majorInterval` to `5 * interval` for the original behavior of every 5th contour line to be a major contour line

### 2024.2.0

*February 6, 2024*

New features:

* Add `palette` to Particle, Contour, Grid, HighLow layers
* Add `imageMinValue` and `imageMaxValue` to Particle, Raster, Contour, Grid, HighLow layers

Minor changes:

* Improve Particle layer performance
  * ⚠️ Use `ClipExtension` to hide particles outside of Mercator bounds
* Merge `getRasterPoints` function arguments to `ImageProperties` type
* Update default colors to remove opacity, prefer separate opacity

Peer dependencies:

* Update deck.gl to 8.9.34
* Update geotiff.js to 2.1.2

### 2024.1.1

*January 23, 2024*

Bug fixes:

* Fix rendering of regional data at left/right bound

### 2024.1.0

*January 14, 2024*

Minor changes:

* Update TooltipControl `followCursor` position origin between value and direction
* Update TooltipControl direction icon

Bug fixes:

* Fix interpolating nodata values at data edges

Peer dependencies:

* Update deck.gl to 8.9.33
* Update geotiff.js to 2.1.1

### 2023.12.1

*December 21, 2023*

New features:

* Add `density` to GridLayer

### 2023.12.0

*December 2, 2023*

New features:

* Add WebP support for custom data
* Enable picking in OpenLayers
* Add `minZoom`, `maxZoom` to all layers
  * ContourLayer has default `maxZoom = 10`. ParticleLayer has default `maxZoom = 15`. Other layers have no default values.
  * It's possible to override a lower default value to a higher value, but rendering artifacts may occur in high zoom levels due to a low precision.

Bug fixes:

* Fix parsing hex colors in RasterLayer palette\
  <https://github.com/weatherlayers/cpt2js/issues/3>
* Fix TooltipControl z-index for Leaflet

### 2023.11.1

*November 3, 2023*

Bug fixes:

* Drop grid points out of bounds

### 2023.11.0

*November 3, 2023*

New features:

* Add direction arrow icon to TooltipControl
* Add `directionFormat` to TooltipControl
* Add `followCursor` to TooltipControl

Peer dependencies:

* Update deck.gl to 8.9.32
* Update geotiff.js to 2.1.0

### 2023.10.3

*October 14, 2023*

New features:

* Enable picking in Mapbox/MapLibre interleaved mode

Bug fixes:

* Fix rendering incorrect nodata pixels in Safari

### 2023.10.2

*October 14, 2023*

Bug fixes:

* Use scoped CSS class names to avoid conflicts with global CSS class names

### 2023.10.1

*October 14, 2023*

Bug fixes:

* Fix basemap flickering due to ParticleLayer animation in MapLibre/Mapbox interleaved mode

Dependencies:

* Update deck.gl to 8.9.31

### 2023.10.0

*October 5, 2023*

New features:

* Add support for single-band Uint8 data format

### 2023.9.0

*September 30, 2023*

Bug fixes:

* Fix disabling layers in MapLibre/Mapbox interleaved mode
* Discard displaying obsolete points in HighLowLayer
* Download GeoTIFF file in a single request

Dependencies:

* Update deck.gl to 8.9.30

### 2023.8.1

*September 5, 2023*

Bug fixes:

* Fix corrupted build (internal dependencies missing in the bundle by mistake)

### 2023.8.0

*September 5, 2023*

Minor changes:

* Add support for license development domains

Bug fixes:

* Fix controls to be clickable when added as MapLibre/Mapbox control

Dependencies:

* Update deck.gl to 8.9.27

### 2023.5.1

*May 21, 2023*

Bug fixes:

* Fix bundling with Webpack

### 2023.5.0

*May 16, 2023*

Minor changes:

* Add loader to TimelineControl
* Add LogoControl

### 2023.4.3

*May 5, 2023*

Bug fixes:

* Fix TimelineControl compatibility with older browsers

### 2023.4.2

*May 4, 2023*

Minor changes:

* Add `fps` config property to TimelineControl

### 2023.4.1

*May 4, 2023*

Bug fixes:

* Fix TimelineControl compatibility with older browsers

### 2023.4.0

*April 30, 2023*

New features:

* Add `getRasterPoints` function to get raster points for the given positions

Minor changes:

* Add `offsetDatetime` and `offsetDatetimeRange` functions to add hours to the given datetime
* Remove unused `loadText` function

Bug fixes:

* Verify that the library is deployed on a secure origin
* Verify that the license has an expected type before verifying the signature
* Log image URL if image decoding fails

Dependencies:

* Update deck.gl to 8.9.9

### 2023.3.4

*April 4, 2023*

Bug fixes:

* Fix broken build

### 2023.3.3

*April 4, 2023*

Bug fixes:

* Fix browser crash when ESM build is used with Vite

Dependencies:

* Update deck.gl to 8.9.6

### 2023.3.2

*March 31, 2023*

Minor changes:

* Update selected datetime in TimelineControl when updating the datetime from outside
* Add `pause` and `reset` methods to TimelineControl
* Add `datetimeFormatFunction` to TimelineControl
* Add `DatetimeISOString` type

### 2023.3.1

*March 31, 2023*

Minor changes:

* Optimize bundle size

Bug fixes:

* Update package exports to expose a default export for TS moduleResolution = node and unpkg.com
* Update TS typings to enable arbitrary layer props such as layer extensions

### 2023.3.0

*March 29, 2023*

New features:

* Publish as npm package
  * Install the library with `npm install weatherlayers-gl`
  * Use the library with `import WeatherLayers from 'weatherlayers-gl'`
* Update licensing approach to a separate `license.json` file
  * [Contact us](mailto:support@weatherlayers.com) to receive your license file
  * Provide the license file to the library with `WeatherLayers.setLicense(license)`
* Migrate to TypeScript
  * Typing files are provided as part of the distribution package
* Add [Front layer](/weatherlayers-gl/layers/front-layer)

Minor changes:

* Add `image2`, `imageSmoothing` and `imageWeight` to HighLow layer
* Improve HighLow layer performance when zooming in/out
* Add `toggle`, `start`, `stop`, `stepBackward` and `stepForward` methods to TimelineControl

Bug fixes:

* Prefer default values over provided `undefined` values
* Remove references to `worker_threads` Node dependency

Peer dependencies:

* Update deck.gl to 8.9.4

### 2023.2.1

*March 20, 2023*

Bug fixes:

* Remove references to `worker_threads` Node dependency

### 2023.2.0

*February 16, 2023*

New features:

* Add cubic interpolation for smoother visualization\
  Rename `imageInterpolate` data property to `imageInterpolation`, change type from boolean to enum\
  Add `imageSmoothing` data property

Bug fixes:

* Fix parsing palettes with values in scientific notation\
  <https://github.com/weatherlayers/cpt2js/issues/2>
* Clamp to edge data on poles

### 2022.11.0

*November 17, 2022*

Minor changes:

* Add `unitFormat` to Grid and HighLow layer for consistent value formatting across layers and controls
* Add [Load Functions](/weatherlayers-gl/functions#load-functions) for loading custom data

### 2022.10.0

*October 14, 2022*

New features:

* Add [Controls](/weatherlayers-gl/controls)

Bug fixes:

* Fix Particle layer to drop particles out of bounds, to support regional vector data\
  <https://github.com/weatherlayers/deck.gl-particle/issues/10>

Minor changes:

* Rename HighLow and Grid layer `textFunction` style property to `textFormatFunction`

Peer dependencies:

* Update deck.gl to 8.8.4

### 2022.6.0

*July 8, 2022*

New features:

* Add [Contour layer](/weatherlayers-gl/layers/contour-layer) computed on GPU for animation support\
  Replace previous Contour layer computed on CPU

Bug fixes:

* Fix half-pixel data rendering misalignment

Minor changes:

* Remove deprecated Raster layer `colormapBreaks` style property, use `palette` instead
* [Demo](https://demo.weatherlayers.com/) - separate overlaid and interleaved demos

Peer dependencies:

* Update deck.gl to 8.8.2

### 2022.5.0

*June 3, 2022*

New features:

* Add support for color palette text format\
  Deprecate raster layer `colormapBreaks` style property, use `palette` instead\
  <https://github.com/weatherlayers/cpt2js>[\
  https://github.com/stac-extensions/raster/issues/17](https://github.com/stac-extensions/raster/issues/17)\
  <https://github.com/radiantearth/stac-spec/pull/1181>

### 2022.4.0

*May 11, 2022*

New features:

* Use [Calendar Versioning](https://calver.org/)
* Add [Grid layer](/weatherlayers-gl/layers/grid-layer)

Bug fixes:

* Fix particle layer breaking in deck.gl auto-offset mode at zoom >= 12 on Mac M1\
  <https://github.com/weatherlayers/deck.gl-particle/issues/5>
* Fix raster layer opacity with Google Maps vector basemap\
  <https://github.com/visgl/deck.gl/issues/6296>\
  <https://github.com/visgl/deck.gl/pull/6804>
* Fix raster layer disappearing in deck.gl auto-offset mode at zoom >= 12\
  <https://github.com/visgl/deck.gl/issues/6798>\
  <https://github.com/visgl/deck.gl/pull/6801>

Minor changes:

* [Demo](https://demo.weatherlayers.com/) - add standalone demos without deck.gl (experimental)

Peer dependencies:

* Update deck.gl to 8.7.5


# Roadmap

* Contour layer with labels
* High-resolution tiled data (COG)


# WeatherLayers Cloud

WeatherLayers Cloud is a cloud service providing visualization-ready weather data from global public weather data sources.

Peer dependencies:

* [geotiff.js](https://github.com/geotiffjs/geotiff.js/) >= 2.0.0 (if loading GeoTIFF images)

### Versioning

WeatherLayers Cloud uses [Calendar Versioning](https://calver.org/) schema `YYYY.MM.MICRO`, e.g. `2022.4.0`.


# Quick Start

### Installation

```
npm install weatherlayers-gl
```

### Trial Usage

```javascript
import * as WeatherLayersClient from 'weatherlayers-gl/client';

// use your WeatherLayers Cloud access token
const client = new WeatherLayersClient.Client({
  accessToken: 'xxx',
});
```

A valid access token is required to use the library. Sign up at [WeatherLayers Account](https://account.weatherlayers.com/) to get your access token.

### Production Usage

The trial access token is valid for 30 days. After the trial period, the pricing is pricing is a flat fee of 300 EUR or 360 USD / year for one application. The application is defined by the production domain, includes unlimited amount of development or test domains.


# Architecture

WeatherLayers Cloud is a caching proxy with no periodic preloading.

When any user accesses a file for the first time, this when the file is downloaded from the upstream data source, processed and cached. Each such first request is expected to take a longer time to finish, depending on the upstream data source response time. All subsequent requests for the same file are served from the cache, either WeatherLayers internal cache or Cloudflare.

This optimises for common usage pattern of users who access the current files or closer forecast offsets over further future forecast offsets.

WeatherLayers Cloud doesn’t support an automated scripted usage requesting all forecast offsets upfront on a periodical schedule.


# Client

Client providing access to weather data from WeatherLayers Cloud or a compatible catalog

### Example

Configure client with your WeatherLayers Cloud access token created in [WeatherLayers Account](https://account.weatherlayers.com/).

```javascript
import * as WeatherLayersClient from 'weatherlayers-gl/client';

// use your WeatherLayers Cloud access token
const client = new WeatherLayersClient.Client({
  accessToken: 'xxx',
  datetimeInterpolate: true,
});

// load dataset slice, load data in the first available datetime
const dataset = 'gfs/wind_10m_above_ground';
const {title, unitFormat, attribution, referenceDatetimeRange, palette} = await client.loadDataset(dataset);
const {datetimes} = await client.loadDatasetSlice(dataset, datetimeRange);
const datetime = datetimes[0];
const {image, image2, imageWeight, imageType, imageUnscale, bounds} = await client.loadDatasetData(dataset, datetime);
```

### Example: Load current data

```javascript
// load current data
const dataset = 'gfs/wind_10m_above_ground';
const {title, unitFormat, attribution, referenceDatetimeRange, palette} = await client.loadDataset(dataset);
const {image, image2, imageWeight, imageType, imageUnscale, bounds} = await client.loadDatasetData(dataset);
```

### Example: Load data by datetime

```javascript
// calculate the datetime range for visualization as 0-24 forecast
const datetimeRange = WeatherLayers.offsetDatetimeRange(new Date().toISOString(), 0, 24);

// load dataset slice, load data in the first available datetime
const dataset = 'gfs/wind_10m_above_ground';
const {title, unitFormat, attribution, referenceDatetimeRange, palette} = await client.loadDataset(dataset);
const {datetimes} = await client.loadDatasetSlice(dataset, datetimeRange);
const datetime = datetimes[0];
const {image, image2, imageWeight, imageType, imageUnscale, bounds} = await client.loadDatasetData(dataset, datetime);
```

### Constructor

#### `Client(config:` [`ClientConfig`](/weatherlayers-cloud/types#clientconfig) `= {})`

### Config properties

#### `url`

Type: string, optional

Default: `https://catalog.weatherlayers.com` (WeatherLayers Cloud)

Catalog url

#### `accessToken`

Type: string, optional

Default: none (but required for WeatherLayers Cloud)

Catalog access token

#### `dataFormat`

Type: string, optional

Default: `byte.png`

GeoTIFF requires [geotiff.js ](https://github.com/geotiffjs/geotiff.js/)as a peer dependency.

#### `unitSystem`

Type: [`UnitSystem`](/weatherlayers-cloud/types#unitsystem), optional

Default: `METRIC`

Unit system for unit format definition.

#### `attributionLinkClass`

Type: string, optional

Attribution link class, used in `Dataset`, `attribution` field

#### `datetimeStep`

Type: number, optional

Default: `1`

Minimal step in hours between datetimes.

#### `datetimeInterpolate`

Type: boolean, optional

Enable datetime interpolation.

For example, if a datetime 6:30 is requested, but 6:00 and 7:00 exist, `{ image: <6:00>, image2: <7:00>, imageWeight: 0.5 }` is returned by `loadDatasetData`.

### Methods

#### `loadCatalog(): Promise<string[]>`

Loads dataset ids from the catalog.

#### `loadDataset(dataset: string, config:` [`ClientConfig`](/weatherlayers-cloud/types#clientconfig) `= {}): Promise<`[`Dataset`](/weatherlayers-cloud/types#dataset)`>`

Loads dataset metadata from the catalog.

#### `loadDatasetSlice(dataset: string, datetimeRange:` [`DatetimeISOStringRange`](/weatherlayers-cloud/types#datetimeisostringrange)`, config:` [`ClientConfig`](/weatherlayers-cloud/types#clientconfig) `= {}): Promise<`[`DatasetSlice`](/weatherlayers-cloud/types#datasetslice)`>`

Loads dataset slice with available datetimes in the given datetime range from the catalog.

The current data with offset can be loaded by providing `datetimeRange = WeatherLayers.offsetDatetimeRange(new Date().toISOString(), 0, 24)`.

#### `loadDatasetData(dataset: string, datetime?:` [`DatetimeISOString`](/weatherlayers-cloud/types#datetimeisostring)`, config:` [`LoadConfig`](/weatherlayers-cloud/types#loadconfig) `= {}): Promise<`[`DatasetData`](/weatherlayers-cloud/types#datasetdata)`>`

Loads dataset data at the given datetime from the catalog. If the datetime is not provided, the current data is loaded.


# Types

### Load Types

#### `ClientConfig`

```typescript
interface ClientConfig {
  url?: string;
  accessToken?: string;
  dataFormat?: string;
  unitSystem?: UnitSystem;
  attributionLinkClass?: string;
  datetimeStep?: number;
  datetimeInterpolate?: boolean;
}
```

#### `LoadConfig`

```typescript
export interface LoadConfig extends ClientConfig {
  tile?: { z: number; x: number; y: number };
  signal?: AbortSignal;
}
```

Data request load config.

* `tile` - tile XYZ coordinates for loading tiled data
* `signal` - abort signal for cancelling the request

#### `Dataset`

```typescript
interface Dataset {
  title: string;
  unitFormat: UnitFormat;
  attribution: string;
  bounds: [number, number, number, number];
  datetimeRange: OpenDatetimeISOStringRange;
  datetimes: DatetimeISOString[]; // deprecated, use `loadDatasetSlice` instead
  palette: Palette;
}
```

#### `DatasetSlice`

```typescript
interface DatasetSlice {
  datetimes: DatetimeISOString[];
}
```

Dataset slice with available datetimes in the requested datetime range.

#### `DatasetData`

```typescript
interface DatasetData {
  datetime: DatetimeISOString;
  referenceDatetime: DatetimeISOString;
  horizon: DurationISOString;
  image: TextureData;
  datetime2: DatetimeISOString | null;
  referenceDatetime2: DatetimeISOString | null;
  horizon2: DurationISOString | null;
  image2: TextureData | null;
  imageWeight: number;
  imageType: ImageType;
  imageUnscale: [number, number] | null;
  bounds: [number, number, number, number];
}
```

Dataset data.

* `datetime` - closest start forecast datetime <= requested datetime
* `referenceDatetime` - reference datetime of `datetime`, i.e. datetime of model run
* `horizon` - duration between `referenceDatetime` and `datetime`, e.g. `PT6H` for a 6-hour forecast
* `image` - image at `datetime`
* `datetime2`\* - closest end forecast datetime >= requested datetime
* `referenceDatetime2`\* - reference datetime of `datetime2`, i.e. datetime of model run
* `horizon2`\* - duration between `referenceDatetime2` and `datetime2`, e.g. `PT6H` for a 6-hour forecast
* `image2`\* - image at `datetime2`
* `imageWeight`\* - interpolation weight between `image` and `image2`
* `imageType` - image type, scalar or vector
* `imageUnscale` - original data value bounds, used to unscale the data if the original data are scaled (quantized)
* `bounds` - original data bounding box

\* applicable only if `datetimeInterpolate` is enabled

#### `TextureData`

```typescript
interface TextureData {
  data: Uint8Array | Uint8ClampedArray | Float32Array;
  width: number;
  height: number;
}
```

Texture data to be used as input to raster rendering layers.

#### `UnitSystem`

```typescript
enum UnitSystem {
  METRIC = 'METRIC',
  METRIC_KILOMETERS = 'METRIC_KILOMETERS',
  IMPERIAL = 'IMPERIAL',
  NAUTICAL = 'NAUTICAL',
}
```

Unit system for unit format definition.

#### `UnitFormat`

```typescript
interface UnitFormat {
  unit: string;
  scale?: number;
  offset?: number;
  decimals?: number;
}
```

Format definition to be used for formatting raw values with units.

### Datetime Types

#### `DatetimeISOString`

```typescript
type DatetimeISOString = string;
```

Valid ISO 8601 datetime.

#### `DatetimeISOStringRange`

```typescript
type DatetimeISOStringRange = [start: DatetimeISOString, end: DatetimeISOString];
```

Valid ISO 8601 datetime range.

#### `OpenDatetimeISOStringRange`

```typescript
type OpenDatetimeISOStringRange = [start: DatetimeISOString | null, end: DatetimeISOString | null];
```

Valid ISO 8601 datetime range. Null start/end represent an open end.

#### `DurationISOString`

```typescript
type DurationISOString = string;
```

Valid ISO 8601 duration.


# Security

### Content Security Policy (CSP)

#### img-src

`catalog.weatherlayers.com` - used by WeatherLayers Client

#### connect-src

`catalog.weatherlayers.com` - used by WeatherLayers Client


# Troubleshooting

### TypeScript integration can't find WeatherLayers Client typings

#### Issue

WeatherLayers Client typings are exported as a separate named export with `exports` syntax.

```typescript
  "exports": {
    ".": {
      "require": "./dist/weatherlayers-deck.min.cjs",
      "import": "./dist/weatherlayers-deck.min.js",
      "script": "./dist/weatherlayers-deck.umd.min.js",
      "types": "./dist/weatherlayers-deck.d.ts"
    },
    "./client": {
      "require": "./dist/weatherlayers-client.min.cjs",
      "import": "./dist/weatherlayers-client.min.js",
      "script": "./dist/weatherlayers-client.umd.min.js",
      "types": "./dist/weatherlayers-client.d.ts"
    }
  },
```

#### Symptoms

After WeatherLayers Client is imported with `import * as WeatherLayersClient from 'weatherlayers-gl/client'`, TypeScript reports that the module `weatherlayers-gl/client` can't be found and TypeScript integration doesn't work.

#### Solution

Check your `moduleResolution` in `tsconfig.json`.

Since TypeScript 5.0, there is a new value `bundler`, which allows covers exactly this case and should be compatible with modern development stacks.

Since TypeScript 5.2, this value is required.

See[ https://github.com/microsoft/TypeScript/pull/54567](< https://github.com/microsoft/TypeScript/pull/54567>) for details.

<figure><img src="/files/8s5QYVWgOaJ8NWJVw50s" alt=""><figcaption></figcaption></figure>


# Datasets

Available datasets are based on public data provided by various providers. The data are automatically updated in a periodical schedule and processed for the visualization. Each dataset has its own update frequency and retention policy.

Details are available in [WeatherLayers Browser](https://browser.weatherlayers.com).


# Pricing

Monthly or yearly subscription.

### Subscription

#### Trial Subscription

Trial Subscription allows evaluating the service for a limited time of 30 days.

Free

#### Single Domain Subscription

Single Domain Subscription is bound to a single production domain, includes all corresponding subdomains.

300 EUR/year


# Changelog

### 2025.11.0

*November 16th, 2025*

New features:

* Add support for loading data with abort signal
  * This loads data with `fetch` as a blob instead of as an image
* Add `bounds` to `loadDataset` response
* Set default data format to WebP

### 2025.3.0

*March 3rd, 2025*

New features:

* Update `loadDatasetData` function `datetime` param to be optional to support loading current data

### 2024.9.0

*September 22nd, 2024*

Minor changes:

* Upgrade to STAC 1.1.0

### 2024.8.2

*August 23rd, 2024*

Bug fixes:

* Validate `datetimeRange` in `loadDatasetSlice`

### 2024.8.1

*August 20th, 2024*

Minor changes:

* Replace TS enums with string constants for cross-bundle compatibility between `weatherlayers-gl` and `weatherlayers-gl/client`
  * <https://www.totaltypescript.com/books/total-typescript-essentials/deriving-types#using-as-const-for-javascript-style-enums>

### 2024.8.0

*August 11th, 2024*

New features:

* Add `UnitSystem.METRIC_KILOMETERS` to allow selecting `km/h` unit

Minor changes:

* Split `UnitDefinition` interface (with `UnitSystem`) from `UnitFormat` interface (without `UnitSystem`)
* Update `datetimeRange` in `loadDataset` response to be open-ended

Bug fixes:

* Fix `referenceDatetime`, `horizon` in `loadDatasetData` response to match the returned data image

### 2024.7.0

*July 20, 2024*

New features:

* Add `datetimeStep` config property
* Add `datetime`, `referenceDatetime`, `horizon` to `loadDatasetData` response

### 2023.8.0

*September 5, 2023*

New features:

* Add `unitSystem` config property

### 2023.5.1

*May 21, 2023*

Bug fixes:

* Fix loading historical data

### 2023.4.0

*April 30, 2023*

New features:

* Add `loadDatasetSlice` function to support loading historical data

Minor changes:

* Use JSON palette instead of plain text


# Roadmap

* On-premise deployment
* Cache warm-up


# Contact

Looking for another data source or dataset? Found a bug? Interested in integrating weather layers into your existing map application? [Get in touch!](mailto:info@weatherlayers.com)


