Skip to content

Docs add deckgl raster tutorial#530

Open
aboydnw wants to merge 4 commits into
microsoft:developfrom
aboydnw:docs-add-deckgl-raster-tutorial
Open

Docs add deckgl raster tutorial#530
aboydnw wants to merge 4 commits into
microsoft:developfrom
aboydnw:docs-add-deckgl-raster-tutorial

Conversation

@aboydnw
Copy link
Copy Markdown
Contributor

@aboydnw aboydnw commented Jun 2, 2026

Based on the outline here

aboydnw and others added 4 commits May 30, 2026 00:11
Adds a tutorial walking through Cloud Optimized GeoTIFF rendering in
the browser with deck.gl-raster — for building standalone web apps
on Planetary Computer data. No companion notebook (TypeScript/React).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The tutorial scaffolded a Vite/React app around APIs that don't work as
written: COGLayer({url}) (the real prop is geotiff:), a backend signing
proxy (the PC sign endpoint is public/anonymous), and colormap/rescale
props COGLayer doesn't have. It also linked a deckgl-raster-example repo
that doesn't exist.

Replace it with a working, committed single index.html: an esm.sh import
map (no build), client-side anonymous signing, COGLayer with a
main-thread DecoderPool (size: 0) to dodge the cross-origin-worker block,
and a MapboxOverlay basemap. Add the rendered-app screenshot and a real
206 range-request log.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace em dashes with sentence splits, commas, and colons, and rename the
trailing-ellipsis section header to a plain statement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the developmentseed/deck.gl-raster examples more closely: interleaved
MapboxOverlay with beforeId so basemap labels stay on top, and
onGeoTIFFLoad -> fitBounds to frame the scene from its own bounds instead
of a STAC bbox. Also make the control panel background solid (it was
slightly transparent and bled the imagery behind it) and refresh the
screenshot.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@aboydnw aboydnw marked this pull request as ready for review June 2, 2026 20:35
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice example of how to have a single-page HTML file with deck.gl-raster! I'll adopt something like this in the deck.gl-raster docs

Comment on lines +112 to +114
// Insert deck layers before the first label layer so basemap text
// (place names, roads) stays legible on top of the imagery.
beforeId = map.getStyle().layers.find((l) => l.type === "symbol")?.id;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too low in the MapLibre layer stack.

If you look at the rendered example:

Image

It's hard to see the image because other layers from the basemap are on top of it.

If you load the map style json (https://basemaps.cartocdn.com/gl/positron-gl-style/style.json), you can try different id values from the layers array.

In my example I use this:
https://github.com/developmentseed/deck.gl-raster/blob/55619f8f15c3e8b8696480f5974d6bd49bcfedf1/examples/naip-mosaic/src/App.tsx#L445

layers: [
new COGLayer({
id: "naip",
geotiff,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you pass in a geotiff as-is, deck.gl-raster uses the "default" styling it can infer. But in this case, the default styling it infers is incorrect. It sees 4 bands but it doesn't have a way to know that the fourth band refers to near-infrared data, instead of an alpha band.

You can use this, which you pass into renderTile to render as RGB

@@ -0,0 +1,147 @@
# Rendering Planetary Computer rasters in the browser with deck.gl-raster

[deck.gl-raster](https://github.com/developmentseed/deck.gl-raster) renders Cloud Optimized GeoTIFFs directly in the browser. Its `COGLayer` reads the COG header over HTTP, then streams only the tiles visible in the current viewport, decodes them client-side, reprojects, and renders in WebGL2. No tile server, no intermediate downloads. It's the same model as [Lonboard](./lonboard.md), but in TypeScript for standalone web apps.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[deck.gl-raster](https://github.com/developmentseed/deck.gl-raster) renders Cloud Optimized GeoTIFFs directly in the browser. Its `COGLayer` reads the COG header over HTTP, then streams only the tiles visible in the current viewport, decodes them client-side, reprojects, and renders in WebGL2. No tile server, no intermediate downloads. It's the same model as [Lonboard](./lonboard.md), but in TypeScript for standalone web apps.
[deck.gl-raster](https://github.com/developmentseed/deck.gl-raster) renders Cloud Optimized GeoTIFFs directly in the browser. Its `COGLayer` reads the COG header over HTTP, then streams only the tiles visible in the current viewport, decodes them client-side, reprojects, and renders in WebGL2. No tile server, no intermediate downloads.

I'd take this out or reword it, because generally Lonboard has used Arrow as the reason why it's faster for vector data, but deck.gl-raster doesn't use Arrow at all. The one thing they both share is that they use deck.gl as the underlying engine for powering geospatial visualizations in the browser.

Comment on lines +11 to +12
- Every `@deck.gl/*` and `@luma.gl/core` entry must be the **same version**, since mismatched patch versions throw `deck.gl - multiple versions detected`.
- The `deck.gl-geotiff` entry marks deck, luma, and geotiff as `external` so they resolve to the singletons above rather than being bundled a second time.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes these are really important things to note! We should add this to the upstream deck.gl-raster docs as well.

Comment on lines +129 to +134
Bbox-search returns many items. Sign each href and pass one `COGLayer` per scene. `overlay.setProps({ layers })` diffs them and only reloads what changed:

```js
const layers = signedHrefs.map((href, i) => new COGLayer({ id: `naip-${i}`, geotiff: href, pool }));
overlay.setProps({ layers });
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine for a few scenes, maybe up to 10 or 20, but if you have hundreds of non-overlapping scenes, which fits NAIP perfectly, it's better to use the MosaicLayer, which only loads COGLayers when they're visible currently on the screen. The naip-mosaic example is an example you could point people to

overlay.setProps({ layers });
```

Browser memory is the practical limit. For large mosaics, reach for `MosaicLayer` / `MultiCOGLayer` from the same package, or fall back to a server-side tiler like [titiler](https://developmentseed.org/titiler/).
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I didn't see this.

It's not necessarily browser memory as the limit, because if you load 100 COG layers and they're all off screen, you'll be using very little browser memory, because only those COG headers will be loaded into memory. but it still forces you to load all those COG headers.

Also, don't suggest the MultiCOGLayer here in the context of a mosaic. That's for cases like landsat/sentinel2 where there are multiple separate COGs that are all referencing the same scene and should be composited together.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants