Upgrade Guide v3.3
kepler.gl 3.3 upgrades the rendering stack from deck.gl 8 / luma.gl 8 to deck.gl 9 / luma.gl 9. This is a major dependency upgrade that changes how WebGL resources, shaders, and rendering parameters are handled under the hood. Most kepler.gl users will not need to change application code, but library consumers who extend layers, interact with the WebGL context directly, or depend on internal types should review this guide.
Dependency Changes
react
^18.2.0
^19.0.0
react-dom
^18.2.0
^19.0.0
react-redux
^8.0.5
^9.1.0
react-intl
^6.3.0
^7.0.0
react-map-gl
^7.1.6
^8.1.1
maplibre-gl
^3.6.2
^4.0.0
@deck.gl/*
8.9.x
9.2.11
@luma.gl/*
8.x
9.2.6
@loaders.gl/*
3.x / 4.3.2
4.3.4
math.gl
—
^4.1.0
typescript
4.7.2
5.6.3
Node.js
>=18.18.2
>=20.19.3
New dependencies
@vis.gl/react-maplibre
8.1.1
MapLibre bindings for react-map-gl 8
maplibregl-mapbox-request-transformer
^0.0.2
Mapbox-style URL transform for MapLibre
@deck.gl-community/editable-layers
9.2.8
Replaces @nebula.gl/layers for editor layer
@deck.gl-community/layers
9.2.8
Community layers package
@deck.gl/widgets
9.2.11
New deck.gl 9 module
@luma.gl/effects
9.2.6
New luma.gl 9 module
@luma.gl/webgpu
9.2.6
Dev dependency for test environment
Removed dependencies
hubble.gl/core, hubble.gl/react
Removed from kepler.gl
@nebula.gl/layers
Replaced by @deck.gl-community/editable-layers
Yarn resolutions
All @deck.gl/*, @loaders.gl/*, and @luma.gl/* packages are pinned via resolutions. If your project has its own resolutions for these packages, make sure they are consistent with the versions above.
Breaking Changes — React 19
kepler.gl 3.3 requires React 19. React 18 is no longer supported.
Removed legacy lifecycle methods
All usage of deprecated lifecycle methods (componentWillReceiveProps, componentWillMount) has been removed. If you have custom components extending kepler.gl internals that rely on these methods, migrate them to componentDidUpdate, getDerivedStateFromProps, or hooks.
ref handling
React 19 passes ref as a regular prop. If you have custom wrapper components using React.forwardRef around kepler.gl components, these will still work but forwardRef is no longer required for new components.
Strict Mode
React 19 enforces stricter Strict Mode behavior. If your application uses <React.StrictMode>, you may notice double-invocation of effects during development. This does not affect production builds.
react-redux v9
The upgrade to react-redux@^9.1.0 drops the legacy context API. Ensure you are not relying on the removed store prop passed directly to connected components — use <Provider store={store}> at the root instead.
react-intl v7
react-intl is upgraded to v7. If your app provides custom format configurations or uses intlShape, consult the react-intl 7.x migration guide.
Upgrading custom components
If you use kepler.gl's dependency injection to replace built-in components:
Replace any class components with function components using hooks
Remove
defaultPropsdeclarations — use default parameter values insteadUpdate any
propTypesusage (still functional but no longer shipped with kepler.gl)
Breaking Changes — Map Libraries
react-map-gl 8 and maplibre-gl 4
react-map-gl is upgraded from ^7.1.6 to ^8.1.1, and maplibre-gl from ^3.6.2 to ^4.0.0. A new dependency @vis.gl/react-maplibre (8.1.1) has been added.
If your application imports from react-map-gl directly (e.g., for custom map overlays), review the react-map-gl 8.x upgrade guide for API changes.
maplibre-gl 4
maplibre-gl v4 includes breaking changes to the style specification and internal rendering pipeline. If you use maplibregl directly or supply custom map styles, consult the maplibre-gl v4 changelog.
Breaking Changes — Node.js
Minimum Node.js version raised to 20
The minimum required Node.js version is now 20.19.3 (previously 18.18.2). Update your CI and development environments accordingly:
Breaking Changes — Layers
HeatmapLayer rewritten from Mapbox GL to deck.gl
HeatmapLayer no longer extends MapboxGLLayer. It now extends the base Layer class and renders using a deck.gl-based implementation.
Impact:
If you extended
HeatmapLayeror relied on its Mapbox GL internals, your subclass will break.The layer config type changed from
MapboxLayerGLConfigtoLayerBaseConfig.New visual config properties:
intensity,threshold,aggregation.A new column mode
COLUMN_MODE_GEOJSONis supported.
If you have custom code that checks layer instanceof MapboxGLLayer for heatmap layers, update it to check layer instanceof Layer or use layer.type === 'heatmap'.
layerOrder type changed
The layerOrder property in visState changed from a flat string[] to LayerOrderEntry[], where:
If your application reads or manipulates state.keplerGl.*.visState.layerOrder directly (e.g., for custom layer reordering), update your code to handle mixed arrays of layer IDs and group objects. Use the helper getFlatLayerOrder(layerOrder) from @kepler.gl/utils to get a flat list of layer IDs.
Breaking Changes — Removed Exports
LayerSelectorPanelFactory removed
LayerSelectorPanelFactory is no longer exported from @kepler.gl/components. If you were using dependency injection to replace this factory, the functionality has been reorganized — use the layer list panel and layer group components instead.
setLayerBlending removed
The function setLayerBlending (previously exported from @kepler.gl/utils) is removed. Use getLayerBlendingParameters instead, which returns a parameters object for deck.gl 9.
Breaking Changes — Behavior
preserveDrawingBuffer disabled by default
The base map's WebGL context previously set preserveDrawingBuffer: true unconditionally. It is now false by default and only enabled during image/video export (isExport: true).
Impact: If your application calls canvas.toDataURL() or canvas.toBlob() on kepler.gl's map canvas outside of the built-in export flow, the canvas will now return blank data. To restore the old behavior, pass preserveDrawingBuffer: true via bottomMapContainerProps in your MapContainer override.
GEOCODER_ICON_SIZE constant changed
GEOCODER_ICON_SIZE changed from 80 to 160 to compensate for anchor normalization in the new rendering stack. If you import this constant for custom geocoder styling, the rendered pin size should remain the same visually — but if you used the raw value for calculations, update accordingly.
Breaking Changes for Library Consumers
1. WebGL context callback renamed
The DeckGL component callback changed from onWebGLInitialized to onDeviceInitialized. The callback now receives a luma.gl Device instead of a raw WebGLRenderingContext.
If you override MapContainerFactory and rely on the initialization callback:
2. Layer blending is now declarative
In deck.gl 8, kepler.gl called setParameters(gl, {...}) with GL constants before each render to set blending mode. In deck.gl 9, blending is set via a parameters prop on DeckGL using WebGPU-style string constants.
Old (removed):
New:
If your application calls setParameters for blending, migrate to the parameters prop instead.
3. GPU parameter constants
A new module @kepler.gl/constants exports WebGPU-style string constants that replace the old GL enum values throughout the codebase:
BLEND_FACTOR—'zero','one','src-alpha', etc.BLEND_OPERATION—'add','subtract', etc.FILTER_MODE—'nearest','linear'ADDRESS_MODE—'clamp-to-edge','repeat','mirror-repeat'TEXTURE_FORMAT—'r8uint','rgba8unorm', etc.TOPOLOGY—'triangle-list','triangle-strip', etc.
If you referenced GL constants for kepler.gl layer configuration, switch to these string constants.
4. setLayerBlending removed
The function setLayerBlending (previously exported from @kepler.gl/utils) is removed. Use getLayerBlendingParameters instead, which returns a parameters object for deck.gl 9.
5. Aggregation layers use deck.gl 9 native CPU aggregation
GridLayer and HexagonLayer now use deck.gl 9's built-in CPU aggregation (gpuAggregation: false) instead of kepler.gl's custom CPUAggregator. This means:
onSetColorDomain/onSetElevationDomaincallbacks now receive[min, max]number arrays instead of{domain, aggregatedBins}objects.Per-bin filtering is applied at the accessor level (
getColorValue,getElevationValue) rather than via a_filterDataprop.ClusterLayerstill uses the internalCPUAggregator.
If you listen to domain callbacks on aggregation layers, update your handler to accept the new format:
6. Shader changes — GLSL 300 es and UBOs
All custom shaders now target GLSL 300 es:
attribute→in,varying→in/outtexture2D()→texture()gl_FragColor→ explicitout vec4 fragColorUniforms are declared inside Uniform Buffer Objects (UBOs) instead of standalone
uniformdeclarations. For example,uniform float opacitybecomes a field inside auniform layerUniforms { float opacity; } layer;block, accessed aslayer.opacity.
If you have custom layers that inject into kepler.gl's shaders (via editShader or shader hooks), review the new GLSL 300 es syntax.
7. Model API changes in custom layers
If you extend any kepler.gl layer and interact with Model objects:
The _getModel(gl) pattern is replaced — models are now created from super._getModel() and modified via model.setGeometry().
8. PickInfo type change
A custom PickInfo<DataT> type is now defined in @kepler.gl/types. This type is a relaxed version of deck.gl 9's PickingInfo to work around stricter generic inference in the DeckGL component's callback types. If you import PickingInfo from @deck.gl/core, be aware that kepler.gl's callbacks use PickInfo instead.
9. MapViewState type is locally defined
MapViewState is no longer imported from @deck.gl/core/typed. It is defined locally in @kepler.gl/types (from reducers.d.ts). If you were importing it from deck.gl, import from @kepler.gl/types instead.
10. Editor layers migrated to @deck.gl-community
The editor layer (EditableGeoJsonLayer) is now imported from @deck.gl-community/editable-layers instead of @nebula.gl/layers. If you extend or replace the editor layer factory, update your imports.
11. Lighting effect API changes
CustomDeckLightingEffect (kepler.gl's lighting/shadow effect) has been rewritten for deck.gl 9:
preRender→setup(context)/cleanup(context)lifecyclegetModuleParameters→getShaderModulePropsShadow module uses UBO-based uniforms with
uniformTypesdeclarationsTexture2Dconstructor →device.createTexture()addDefaultShaderModule/removeDefaultShaderModuleAPI ondeckinstance
If you extend CustomDeckLightingEffect, review the new lifecycle methods.
12. MapView with legacyMeterSizes
kepler.gl now creates MapView with {legacyMeterSizes: true} to preserve backward-compatible meter-based sizing behavior from deck.gl 8.
Runtime Patches
kepler.gl 3.3 applies two patches to work around deck.gl 9 / luma.gl 9 issues. These are applied automatically and require no action, but are documented for awareness:
patchDeckRendererForPostProcessing()— PatchesDeckRenderer._resizeRenderBuffersto add depth-stencil attachments to post-processing framebuffers. In deck.gl 9, FBOs are created without depth buffers by default, which breaks depth testing when post-processing effects are active.patchPipelineValidation()— PatchesWEBGLRenderPipeline._getLinkStatusto suppress false-positive "mixed sampler type" validation errors in luma.gl 9. This patch is applied lazily only when a raster tile layer is instantiated.
New Features
3D Tile Layer (experimental)
A new 3D Tile Layer enables rendering of photogrammetry meshes, buildings, terrain and other 3D content from OGC 3D Tiles and I3S tilesets. Supported providers:
OGC 3D Tiles 1.0 / 1.1 — any standard
tileset.jsonendpoint.Google Photorealistic 3D Tiles — requires a Google Maps API key.
Cesium Ion — requires a Cesium Ion access token.
ArcGIS I3S — scene service endpoints.
Add a 3D tileset via the Add Data → Tilesets modal by selecting the "3D Tile" type. The layer supports opacity, point size configuration, zoom-to-layer, and the Light and Shadow effect. See the 3D Tile Layer user guide for details.
Flow Layer
A new Flow Layer renders origin-destination flows as animated arcs with directional particles.
Bitmap Overlay Layer
A new Bitmap Overlay Layer renders georeferenced raster images (PNG, JPEG) on the map.
Swipe Compare Mode
A new map split mode (MapSplitMode.SWIPE_COMPARE) enables side-by-side comparison of layers using a draggable divider. Use the setMapSplitMode action to switch between SINGLE_MAP, DUAL_MAP, and SWIPE_COMPARE.
Annotations
A new annotation system allows adding text labels, markers, and shapes directly on the map. New actions: addAnnotation, removeAnnotation, updateAnnotation, duplicateAnnotation, setSelectedAnnotation.
Layer Groups
Layers can now be organized into named groups with shared visibility and legend controls. New actions: addLayerGroup, removeLayerGroup, updateLayerGroup, addLayerToLayerGroup, removeLayerFromLayerGroup.
Other New Features
Zoom and compass controls — on-map navigation buttons
Tooltip toggle — ability to disable tooltips per-map
Higher pitch option — configurable maximum pitch beyond the default 60°
GeoJSON mode for aggregation layers — aggregate by polygon geometry
Labels for GeoJSON layer — text label support on polygon/line features
Rectangle drag-to-filter — streamlined rectangular area filter
Layer visibility toggle in map legend
Locale persistence — locale is included in exported maps and restored on load
Video export with effects — post-processing effects are captured in video export
Non-linear piecewise focus range for VisConfig sliders
CSV/TSV auto-delimiter detection in data processors
Fog post-processing effects
Two new post-processing effects are available:
Distance Fog (
distanceFog) — depth-buffer-based fog that increases with camera distance. Parameters:density,fogStart,fogRange,fogColor.Surface Fog (
surfaceFog) — elevation-based ground fog applied below a configurable height in meters. Parameters:density,height,thickness,fogColor.
Both effects are registered in POSTPROCESSING_EFFECTS and can be created via createEffect(). Only one fog effect can be active at a time (enforced by the effect manager UI). Fog effects are ordered early in the post-processing chain to read the depth buffer before subsequent effects clear it.
Known Issues
Performance with tiled layers on older hardware
The deck.gl 9 upgrade introduces additional per-frame overhead in the layer management and GPU state pipelines compared to deck.gl 8. This may cause noticeable slowness when interacting with tiled layers (Tile3DLayer, raster tile layers) — especially when changing visual properties like opacity or when moving the camera over a scene with many visible tiles. The issue is more pronounced on older or lower-end GPUs and is currently under investigation.
Last updated
Was this helpful?