> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nikaplanet.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Build fullstack map processing with OnlyMapJS

> Pair OnlyMap JS in the browser with NIKA GeoEngine on Kubernetes: run satellite imagery batch jobs from a map and stream COG results with no tile server.

Most geo applications need two halves: a front end that makes large data easy to explore, and a backend that can actually process it. [OnlyMap JS](https://docs.nikaplanet.com/onlymap/overview.md) is the first, NIKA GeoEngine is the second, and they are built to meet in the middle. For more live OnlyMap maps, browse the examples on [onlymap.nikaplanet.com ↗](https://onlymap.nikaplanet.com/).

> [card] Front end: OnlyMap JS
>
> Projection-aware WebGL maps from declarative HTML. Streams COG and Zarr rasters straight from storage, and polls live data.

> [card] Backend: NIKA GeoEngine
>
> Batch jobs that fan out on CPU, high-memory and GPU pools, behind role-based access, writing COG, Zarr and GeoJSON.

## How they connect

![OnlyMap in the browser calls your app API, which submits a batch job to NIKA GeoEngine; tasks write results to storage that OnlyMap streams directly](https://mintcdn.com/nika/joaiHPqbHOs4tvpR/images/geoengine/onlymap-flow-light.svg?fit=max\&auto=format\&n=joaiHPqbHOs4tvpR\&q=85\&s=68d958af367c72f395b1c7da2dad5c59)

![](https://mintcdn.com/nika/joaiHPqbHOs4tvpR/images/geoengine/onlymap-flow-dark.svg?fit=max\&auto=format\&n=joaiHPqbHOs4tvpR\&q=85\&s=418c6ddf7be09ae26f04d663a55b8288)

![](https://mintcdn.com/nika/joaiHPqbHOs4tvpR/images/geoengine/onlymap-flow-tall-light.svg?fit=max\&auto=format\&n=joaiHPqbHOs4tvpR\&q=85\&s=2eb50604176c8c500802c8cee73ad1d8)

![](https://mintcdn.com/nika/joaiHPqbHOs4tvpR/images/geoengine/onlymap-flow-tall-dark.svg?fit=max\&auto=format\&n=joaiHPqbHOs4tvpR\&q=85\&s=53cf2cc1c92b7b4f36ce46dadaf118c3)

* **No tile server in between.** Workers write Cloud-Optimised GeoTIFF or Zarr; OnlyMap's `COGLayer` and `ZarrLayer` read only the parts on screen, by HTTP range request. See [a COG](https://onlymap.nikaplanet.com/display-a-geotiff/) and [a Zarr cube](https://onlymap.nikaplanet.com/slice-a-zarr-cube/) live.
* **Progress is just data.** A layer with `refresh="2s"` polls the job's task list, so tiles light up on the map as tasks finish. [See polling live ↗](https://onlymap.nikaplanet.com/san-francisco-last-mile/).
* **Credentials stay out of markup.** `OmMap.configureData()` adds your token to every data-layer request, polling included, so the task list can sit behind your app's authentication.
* **Rasters are fetched directly by the browser.** `COGLayer` and `ZarrLayer` do not route through `configureData`. Serve COG results same-origin through your app, where the browser sends the user's session cookie, or from a CORS-enabled store. Authenticated Zarr stores are not supported yet, so use Zarr for results that may be public and COG behind your app for sensitive ones.
* **Access control carries through.** A user who isn't cleared for a restricted worker is refused at the gateway, and the map says so.

## Try it

Pick a scenario and run a batch job. Each square is one task on one pod. Switch the scenario to **New-building detection** and run it as an **Analyst** to see a restricted worker refused.

OnlyMap JS on NIKA GeoEngine demo

Demo: the backend's responses are simulated in the page. The map, layers and polling are real OnlyMap JS. For more maps you can play with, see [the OnlyMap examples ↗](https://onlymap.nikaplanet.com/).

## The front-end code

The whole map is markup. Your app API proxies two calls to NIKA GeoEngine: create the job, and return its tasks as GeoJSON.

```html index.html theme={null}
<link rel="stylesheet" href="https://unpkg.com/@nika-js/onlymap@0.12.1/dist/onlymapjs.css">
<script type="module">
  import { OmMap } from "https://unpkg.com/@nika-js/onlymap@0.12.1";
  OmMap.configureData({ headers: { Authorization: `Bearer ${sessionToken}` } });
</script>

<om-map basemap="satellite" center="[5.56, 52.52]" zoom="10">
  <!-- results: a COG written by the batch job, served same-origin by your app and streamed by range request -->
  <om-layer id="ndvi" type="COGLayer"
            src="/results/2026-11/flevoland/ndvi.tif"
            min="0" max="1" colormap="viridis"></om-layer>

  <!-- progress: one polygon per task, re-polled every 2 seconds -->
  <om-layer id="tasks" type="GeoJsonLayer"
            data="https://app.example.com/api/jobs/j-7q2c9xk4/tasks.geojson" refresh="2s"
            get-fill-color="$fill" get-line-color="[255,255,255,140]"
            line-width-min-pixels="1" pickable></om-layer>

  <om-widget type="legend" position="bottom-end"></om-widget>
</om-map>
```

## What teams build with the pair

> [card] Crop monitoring from cloud-free mosaics
>
> **Need:** field-by-field vegetation health every month, despite cloud.
>
> **Backend:** `cloud-removal` builds a monthly Sentinel-2 composite per tile on the high-memory class; a second worker computes mean NDVI per field.
>
> **On the map:** the composite as a `COGLayer`, fields coloured by NDVI, and a month slider with the `filter` widget. Try [a GeoTIFF](https://onlymap.nikaplanet.com/display-a-geotiff/) and [GPU filtering](https://onlymap.nikaplanet.com/filter-on-the-gpu/).

> [card] Flood extent within hours
>
> **Need:** where the water is after a storm, while clouds still cover optical satellites.
>
> **Backend:** your pipeline starts a batch job when a Sentinel-1 radar scene lands; a CPU worker compares it with a dry baseline, tile by tile.
>
> **On the map:** the flood mask over the satellite basemap, with affected roads and facilities as `PopupLayer` badges. Try [labelling many features](https://onlymap.nikaplanet.com/label-many-features/).

> [card] New-building detection at sensitive sites
>
> **Need:** flag construction across very high-resolution imagery of sites few people may see.
>
> **Backend:** a restricted GPU worker runs a change-detection model; only the cleared role can submit it, and results stay in the cluster's storage.
>
> **On the map:** before and after imagery as COGs served through your app, a layer switcher, and detected footprints as polygons for review.

> [card] Burn severity after wildfire
>
> **Need:** a severity map for recovery teams days after containment.
>
> **Backend:** a CPU worker computes dNBR from pre- and post-fire Sentinel-2 scenes, fanned out per tile, and writes a classified COG.
>
> **On the map:** a `COGLayer` with a threshold legend of severity classes, over shaded relief from `HillshadeLayer`. Try [shaded relief](https://onlymap.nikaplanet.com/shade-the-terrain/).

> [card] Heat stress from climate data cubes
>
> **Need:** district-level heat-stress days from decades of reanalysis data.
>
> **Backend:** a high-memory worker reads the cube, computes the index per year and writes a public, CORS-enabled Zarr store plus a district table.
>
> **On the map:** a `ZarrLayer` with a year selector, beside a district choropleth and a chart widget. Try [slicing a Zarr cube](https://onlymap.nikaplanet.com/slice-a-zarr-cube/).

> [card] Drone inspection of solar farms
>
> **Need:** find failing panels from thousands of thermal drone photos per site.
>
> **Backend:** a GPU worker builds the orthomosaic and detects hot spots, one batch per flight.
>
> **On the map:** the orthomosaic as a `COGLayer`, each original photo as a geotagged `ImageOverlay`, and defects clustered by row. Try [placing a drone photo](https://onlymap.nikaplanet.com/place-a-drone-photo/) and [clustering points](https://onlymap.nikaplanet.com/cluster-points/).

## Why the pair works

| Need | OnlyMap JS | NIKA GeoEngine |
| - | - | - |
| Huge rasters | Streams only what is on screen | Processes them on machines sized to fit |
| Many scenes | Shows progress task by task | Fans out across pods |
| Sensitive data | Keeps tokens out of markup; reads sensitive COGs through your app | Restricts workers to cleared roles; data stays in your cluster |
| Projections | Draws in national grids and equal-area projections | Reprojects with GDAL and PROJ in every worker |

## Next steps

> [card] [Build your first worker](https://docs.nikaplanet.com/geoengine/workers.md)
>
> Manifest, inputs and batch habits.

> [card] [Connect your pipeline](https://docs.nikaplanet.com/geoengine/integrations.md)
>
> Your pipelines, FME Flow, ArcGIS.

> [card] [OnlyMap JS docs](https://docs.nikaplanet.com/onlymap/overview.md)
>
> Layers, widgets and live data.

More than 70 live OnlyMap examples, from GeoTIFFs and Zarr cubes to live tracking and 3D, are on [onlymap.nikaplanet.com ↗](https://onlymap.nikaplanet.com/).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.