Live demo: https://noc-oi.github.io/zarr-vis
Article: Zarr in the Browser β Fast, Flexible, and Surprisingly Powerful for Big Geo Data
This project explores fast, scalable methods for visualizing Zarr-based multidimensional data directly in the browser. It evaluates server-side and client-side strategies and demonstrates them in a Next.js application built for interactivity and performance.
Zarr is a powerful format for storing chunked, compressed N-dimensional arrays, widely used in climate and oceanography. However, visualizing Zarr efficiently on the web has remained a challenge. This project implements and compares multiple approaches:
- Server-side dynamic tile rendering with titiler-multidim
- Pure browser-side rendering using WebGL + Mapbox, inspired by carbonplan/maps
- Pure browser-side rendering using WebGL + Mapbox, using zarr-gl
- Optional rendering using Cloud-Optimized GeoTIFFs (COGs) and legacy WMS/WMTS tools like GeoServer
- Visualizes 10GB+ datasets interactively with smooth zoom/pan
- Supports time and depth slicing for 4D datasets
- Dynamically applies colormaps and enables pixel-level inspection
- Deploys in either static or server-backed modes
- Uses Zarr v2 with multiscale pyramids and consolidated metadata
- Generate canvas layers for animated visualizations (e.g., ocean currents)
The demo uses example outputs from the Near Present Day (NPD) NEMO ocean model produced by the National Oceanography Centre (NOC). These datasets are in Zarr format with curvilinear grids and multiple timesteps.
For full details on the preprocessing steps, including reprojection, rechunking, and pyramid generation, see the Medium article.
git clone https://github.com/NOC-OI/zarr-vis.git
cd zarr-visnpm installCreate a .env.local file in the root directory and add your environment variables. You can use the .env.example file as a reference. You can see below an example of the required variables:
NEXT_PUBLIC_MAPBOX_API_KEY=<SOME_API_KEY>
NEXT_PUBLIC_TILE_SERVER_URL=https://imfe-pilot-tileserver.noc.ac.uk/
NEXT_PUBLIC_ZARR_TILE_SERVER_URL=https://atlantis44.xyz/
For the NEXT_PUBLIC_MAPBOX_API_KEY, you can get a free API key by signing up at Mapbox.
npm run devOpen http://localhost:3000 in your browser.
To add your own layers, modify the src/application/data/layers-json.tsx file. You can add Zarr datasets or other compatible layers by following the existing format.
You can see below an example of a Zarr layer configuration:
export const layersJson = {
My_own_layers: { // This is the name of the group of layers that will appear in the frontend
layerNames: {
my_own_carbonplan_layer: { // Unique layer identifier that will be used in the code and frontend
url: "https://atlantis-vis-o.s3-ext.jc.rl.ac.uk/nemotest101/pyramid2/T1d/sos_abs.zarr", // URL to the Zarr dataset
dataType: "carbonplan", // using carbonplan/maps
content:
"Some information about the dataset goes here.",
params: {
variable: "sos_abs" // variable name in the Zarr file
},
dimensions: { // the dimensions available in the dataset besides x and y. This is mandatory for carbonplan/maps
time: {
selected: 0, // default selected index
values: 'range(1,152,1)' // can be an array of values or a range
}
},
dataDescription: ['Salinity', ''], // The description of the data to show in the legend
colors: 'jet', // colormap to use (from matplotlib colormaps)
scale: [30, 37] // min and max values for the color scale
},
my_own_titiler_layer: { // Unique layer identifier that will be used in the code and frontend
url: "https://atlantis-vis-o.s3-ext.jc.rl.ac.uk/nemotest101/T1d/sos_abs.zarr", // URL to the Zarr dataset
dataType: "ZARR", // using titiler-multidim
content:
"Some information about the dataset goes here.",
params: {
variable: "sos_abs" // variable name in the Zarr file
},
dataDescription: ['Salinity', ''], // The description of the data to show in the legend
colors: 'jet', // colormap to use (from matplotlib colormaps)
scale: [30, 37] // min and max values for the color scale
},
}
}
};- Uses titiler-multidim to dynamically generate tiles
- Deployed with FastAPI and auto-scaled via Knative (Kubernetes on JASMIN)
- Optional Redis caching layer for low-latency access
- Streams Zarr tiles directly into WebGL via custom
<CarbonplanLayer>for Mapbox GL JS - Streams Zarr tiles directly into WebGL via
Zarr-gllayer for Mapbox GL JS - Uses multiscale pyramids built with
ndpyramid - No server required β ideal for GitHub Pages or CDN deployment
- GeoServer with NetCDF support was deployed in Kubernetes: Legacy Comparison
- Cloud Optimized GeoTIFFs (COGs) - converted the dataset to COG files, generating one COG per timestep and depth level.
Tools:
xarray,iris,ndpyramid,rasterio,xESMF
- Reproject to EPSG:4326 or EPSG:3857
- Optimize chunking for web (e.g.,
256x256spatial-only chunks) - Build multiscale pyramids using
ndpyramid - Save in Zarr v2 with
.zmetadataconsolidated - Optionally export to NetCDF or COG for legacy tools
For Python snippets and examples, see the article.
Visualizing a 10GB dataset in the browser using a dynamic backend tile server. As you can see, you can easily change the timestamp, colormap, and map scale.
Example of visualizing a 10GB dataset in the browser using a carbonplan/maps adapted code. As you can see, you can easily change the timestamp, colormap, and map scale
Accessing Zarr data using
zarritaand converting it into a canvas layer to represent the animated current fields on a map. You can interact with the dimensions of the data (time and depth).
Accessing Zarr data using
zarritafor pixel-level inspection and creating time series and spatial charts.
This work is part of the Atlantis project, a UK initiative supporting long-term ocean observations and marine science in the Atlantic. This project is led by the National Oceanography Centre (NOC).