Map ProvidersServing Raster Tiles

Serving raster tiles from imagery

GeoAI.js does not build tile pyramids. It fetches raster {z}/{x}/{y} URLs and stitches them for inference. You need an image or raster tile server (or a pre-tiled static pyramid) that exposes Web Mercator tiles your models can consume.

This page covers common ways to go from a GeoTIFF or Cloud Optimized GeoTIFF (COG) to a baseUrl for the TMS provider.

What GeoAI.js needs

RequirementNotes
Raster tilesPNG/JPEG imagery — not vector PBF/MVT basemaps
URL template{z}/{x}/{y} placeholders or legacy baseUrl + extension
Web MercatorDefault scheme: "WebMercator" (XYZ / slippy map)
Aligned map + inferenceUse the same tile URL in MapLibre and geoai.pipeline()
const pipeline = await geoai.pipeline([{ task: "building-detection" }], {
  provider: "tms",
  baseUrl: "https://your-raster-tiles.example.com/tiles/{z}/{x}/{y}.png",
  scheme: "WebMercator",
  attribution: "Your imagery source",
});

See the TMS provider page for URL templates, schemes, and API keys.

Option 1: Managed platform (Geobase)

Best fit for this project — upload or reference a COG, get Web Mercator tile URLs without running your own server.

Pros: No tile-server ops; integrates with storage and auth.
Cons: Requires a Geobase project.

Option 1b: OpenAerialMap / HOT Imagery

Community aerial orthophotos via the public HOT Imagery STAC + TiTiler stack — no API key. Prefer the first-class OAM provider (provider: "oam"), which STAC-searches the AOI and fetches item XYZ tiles (or use mosaic: true / TMS with the mosaic template).

Pros: Free public aerial coverage where contributors have uploaded.
Cons: Sparse global coverage; not a substitute for basemap satellite everywhere.

See examples/07-oam-quickstart for a minimal Vite + MapLibre demo over Rome imagery.

Option 2: Dynamic COG tile servers

Serve tiles on demand from a COG (HTTP range reads, overviews) without pre-rendering a full pyramid.

Tileserver RS

Tileserver RS is a single-binary server with native COG support (type = "cog" in config). It serves raster XYZ tiles with on-the-fly reprojection, resampling, and colormaps. Paths can be local, HTTP(S), or cloud (s3://, etc.). STAC catalog sources are also supported.

Pros: Purpose-built slippy raster tiles; good TMS fit.
Cons: Requires GDAL + raster feature at build time; newer project.

Self-hosted image/raster tile services

You can run any service that reads COGs via GDAL/rio-tiler and exposes {z}/{x}/{y} PNG/JPEG URLs — for example a small FastAPI or Node app using rio-tiler. URL shape varies by deployment; point baseUrl at the template your server documents.

Pros: Full control; can colocate with your data.
Cons: You operate and secure the service.

MapServer (WMS / WCS)

MapServer reads COGs through GDAL (local files or remote /vsicurl/...). It is a strong WMS/WCS server, not a native XYZ tile server.

GeoAI.js can consume MapServer (and GeoServer, QGIS Server, ArcGIS WMSServer) directly via the WMS provider — no MapCache required for inference. For map display, you may still prefer XYZ/TMS via MapCache or TiTiler for simpler MapLibre integration.

Pros: Mature, flexible OGC services; native WMS support in GeoAI.js.
Cons: GetMap per tile can be slower than dedicated XYZ caches; map UI may need extra WMS wiring.

Option 3: Pre-rendered static pyramid (gdal2tiles)

Bake a {z}/{x}/{y} tree offline, then host on S3, nginx, or any static file server.

gdal2tiles.py -z 10-18 --xyz your_imagery.tif ./tiles_output/

--xyz produces Web Mercator layout matching scheme: "WebMercator".

const pipeline = await geoai.pipeline([{ task: "object-detection" }], {
  provider: "tms",
  baseUrl: "https://your-host.example.com/tiles/{z}/{x}/{y}.png",
  scheme: "WebMercator",
});

Pros: Simple static hosting; no runtime tile server.
Cons: Large storage; fixed zoom range; re-tile when source imagery changes.

For traditional TMS Y-flip, omit --xyz and set scheme: "TMS" in GeoAI.

Option 4: MBTiles + raster tile server

Package tiles into .mbtiles, then serve with tileserver-gl or similar. Point baseUrl at the server’s {z}/{x}/{y} template.

Pros: Portable single file; good for demos.
Cons: Pre-processing step; server must expose raster (not vector-only) tiles.

Public imagery smoke test

To verify TMS wiring without your own imagery, use ESRI World Imagery (satellite, no API key):

const pipeline = await geoai.pipeline([{ task: "building-detection" }], {
  provider: "tms",
  baseUrl:
    "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
  scheme: "WebMercator",
  attribution: "© Esri, Maxar, Earthstar Geographics",
});

Note ESRI uses {z}/{y}/{x} in the path (Y before X).

Runnable example

examples/05-tms-quickstart — draw a polygon on ESRI satellite by default, or paste any raster tile URL in the sidebar.

Choosing an approach

ApproachCOG on-the-fly{z}/{x}/{y} TMSOps burden
GeobaseYesYesLow
Tileserver RSYesYesMedium
Self-hosted raster serviceYesYesMedium–high
MapServer (+ tile cache)Yes (input)With extra setupHigh
gdal2tiles (static)No (pre-baked)YesLow at runtime
MBTiles + tile serverNo (pre-baked)YesMedium

For production GeoAI workflows on your own imagery, start with Geobase or a dynamic raster tile server; use gdal2tiles when you want static hosting only.