Skip to content
Console

Base map

ExpTech serves three base-map tile sets. Each has a TileJSON, so you can use it directly as a MapLibre GL JS source:

Tiles Format Contents
Base map Vector (.pbf) World land, boundaries of Taiwan counties, cities, townships, towns, and districts, and coastal segments for tsunami warnings
Terrain Raster (.png, Terrain-RGB) Taiwan elevation, for hillshade or 3D terrain
Streets and buildings Vector (.pbf, OpenMapTiles schema) Taiwan roads, buildings, water, place names, points of interest, and more, from OpenStreetMap

These three tile sets do not change with time. They do not need a time list.

Upstream terms
  • OpenStreetMap: OpenStreetMap data is licensed under the ODbL: show "© OpenStreetMap contributors" on the map and link to https://www.openstreetmap.org/copyright .
  • OpenMapTiles: Tiles built on the OpenMapTiles schema must show "© OpenMapTiles".

Where to show it, examples and commercial-use requests: Data licensing and attribution.

No API Token is required. Responses include Access-Control-Allow-Origin: *, so a browser can load them cross-origin.

GEThttps://lb.exptech.dev/api/v1/map/tiles/tiles.json
ServerLB
Request
curl "https://lb.exptech.dev/api/v1/map/tiles/tiles.json"
Response

TileJSON 2.0.0 (excerpt)

{
"tilejson": "2.0.0",
"name": "ExpTech Studio Map",
"format": "pbf",
"minzoom": 0,
"maxzoom": 12,
"bounds": [
-180,
-85.051129,
180,
83.634101
],
"attribution": "ExpTech Studio Map",
"tiles": [
"https://lb.exptech.dev/api/v1/map/tiles/{z}/{x}/{y}.pbf"
]
}
Try it

The token is sent from your browser directly to the API.

GEThttps://lb.exptech.dev/api/v1/map/tiles/{z}/{x}/{y}.pbf
ServerLB
Path parameters
  • zintegerRequired

    Zoom level. The range is minzoom / maxzoom in the TileJSON.

  • xintegerRequired

    XYZ tile column.

  • yintegerRequired

    XYZ tile row (north to south).

Request
curl -o output.pbf --compressed "https://lb.exptech.dev/api/v1/map/tiles/<z>/<x>/<y>.pbf"
Response

Mapbox Vector Tile (Content-Type: application/octet-stream). Some tiles are gzip-compressed (Content-Encoding: gzip)binary MVT

No tile at this position (no content)No response body

Try it
Path parameters

The token is sent from your browser directly to the API.

source-layer Geometry Contents
global Polygon World land
city Polygon Taiwan counties and cities
town Polygon Taiwan townships, towns, and districts
tsunami Line Coastal segments for tsunami warnings

Property fields for each layer have no published schema and may change.

GEThttps://lb.exptech.dev/api/v1/map/terrain/terrain.json
ServerLB
Request
curl "https://lb.exptech.dev/api/v1/map/terrain/terrain.json"
Response

TileJSON 2.0.0 (excerpt)

{
"tilejson": "2.0.0",
"name": "ExpTech Studio Terrain",
"format": "png",
"encoding": "mapbox",
"minzoom": 0,
"maxzoom": 12,
"bounds": [
120.0166,
21.8939,
122.0096,
25.3015
],
"attribution": "ExpTech Studio Map",
"tiles": [
"https://lb.exptech.dev/api/v1/map/terrain/{z}/{x}/{y}.png"
]
}
Try it

The token is sent from your browser directly to the API.

GEThttps://lb.exptech.dev/api/v1/map/terrain/{z}/{x}/{y}.png
ServerLB
Path parameters
  • zintegerRequired

    Zoom level. The range is minzoom / maxzoom in the TileJSON.

  • xintegerRequired

    XYZ tile column.

  • yintegerRequired

    XYZ tile row (north to south).

Request
curl -o output.png "https://lb.exptech.dev/api/v1/map/terrain/<z>/<x>/<y>.png"
Response

image/png, 512 × 512 Terrain-RGB. A position with no data returns a flat image at sea level (0 m)binary image/png

Try it
Path parameters

The token is sent from your browser directly to the API.

Tiles are 512 × 512 Terrain-RGB PNGs (mapbox encoding). Elevation in meters:

const elevation = -10000 + (r * 256 * 256 + g * 256 + b) * 0.1;

A position outside coverage or without data does not return 204. It returns a 512 × 512 image for sea level (0 m), which MapLibre raster-dem can use directly.

GEThttps://lb.exptech.dev/api/v1/map/gsi/gsi.json
ServerLB
Request
curl "https://lb.exptech.dev/api/v1/map/gsi/gsi.json"
Response

TileJSON 2.0.0 (excerpt)

{
"tilejson": "2.0.0",
"name": "ExpTech Studio GSI (Taiwan roads & buildings)",
"format": "pbf",
"minzoom": 0,
"maxzoom": 14,
"bounds": [
114.28579,
10.32677,
122.3283,
26.43722
],
"attribution": "© OpenStreetMap contributors © OpenMapTiles",
"tiles": [
"https://lb.exptech.dev/api/v1/map/gsi/{z}/{x}/{y}.pbf"
]
}
Try it

The token is sent from your browser directly to the API.

GEThttps://lb.exptech.dev/api/v1/map/gsi/{z}/{x}/{y}.pbf
ServerLB
Path parameters
  • zintegerRequired

    Zoom level. The range is minzoom / maxzoom in the TileJSON.

  • xintegerRequired

    XYZ tile column.

  • yintegerRequired

    XYZ tile row (north to south).

Request
curl -o output.pbf --compressed "https://lb.exptech.dev/api/v1/map/gsi/<z>/<x>/<y>.pbf"
Response

Mapbox Vector Tile (Content-Type: application/octet-stream). Some tiles are gzip-compressed (Content-Encoding: gzip)binary MVT

No tile at this position (no content)No response body

Try it
Path parameters

The token is sent from your browser directly to the API.

Built from OpenStreetMap data for Taiwan, using the OpenMapTiles layer schema, and covering Taiwan only. Common source-layers: transportation, transportation_name, building, water, waterway, water_name, landcover, landuse, park, aeroway, aerodrome_label, boundary, place, poi, mountain_peak, housenumber. Properties for each layer are in the OpenMapTiles documentation. When you use them, you must show “© OpenStreetMap contributors © OpenMapTiles”.

FieldTypeDescription
tilejsonstringTileJSON specification version. Currently 2.0.0.
namestringTile set name.
formatstringpbf (vector) or png (terrain).
encodingstringTerrain only. The value is mapbox (Terrain-RGB encoding).
minzoomintegerMinimum zoom level.
maxzoomintegerMaximum zoom level. Above this, scale up this level's tiles.
boundsnumber[4]Coverage [west, south, east, north], in degrees.
centernumber[3]Suggested initial center [longitude, latitude, zoom].
attributionstringAttribution text that must be shown.
tilesstring[]Tile URL templates (absolute URLs).

Use all three tile sets in one MapLibre GL JS style. Create each source from the TileJSON url, and the zoom range and coverage are read automatically. The attribution inside the TileJSON is not the full suggested credit. Set attribution on the source yourself, as below (it replaces the TileJSON value):

basemap.js
const MAP = "https://lb.exptech.dev";
const map = new maplibregl.Map({
container: "map",
center: [121, 23.7],
zoom: 7,
style: {
version: 8,
sources: {
// Base map: global / city / town / tsunami
exptech: { type: "vector", url: `${MAP}/api/v1/map/tiles/tiles.json`, attribution: "Data: ExpTech Studio (exptech.dev)" },
// Terrain: Terrain-RGB (mapbox encoding)
terrain: { type: "raster-dem", url: `${MAP}/api/v1/map/terrain/terrain.json`, tileSize: 512, encoding: "mapbox", attribution: "Data: ExpTech Studio (exptech.dev)" },
// Taiwan streets and buildings: OpenMapTiles schema
gsi: { type: "vector", url: `${MAP}/api/v1/map/gsi/gsi.json`, attribution: "Data: © OpenStreetMap contributors, © OpenMapTiles, ExpTech Studio (exptech.dev)" },
},
layers: [
{ id: "background", type: "background", paint: { "background-color": "#1f2329" } },
{ id: "land", type: "fill", source: "exptech", "source-layer": "global", paint: { "fill-color": "#3e4147" } },
{ id: "county", type: "fill", source: "exptech", "source-layer": "city", paint: { "fill-color": "#4b4e55" } },
{ id: "hillshade", type: "hillshade", source: "terrain", paint: { "hillshade-exaggeration": 0.3 } },
{ id: "roads", type: "line", source: "gsi", "source-layer": "transportation", paint: { "line-color": "#8a8f98", "line-width": 1 } },
{ id: "buildings", type: "fill", source: "gsi", "source-layer": "building", minzoom: 13, paint: { "fill-color": "#5a5e66" } },
{ id: "town-line", type: "line", source: "exptech", "source-layer": "town", paint: { "line-color": "#a9b4bc", "line-width": 0.4 } },
{ id: "county-line", type: "line", source: "exptech", "source-layer": "city", paint: { "line-color": "#a9b4bc", "line-width": 1 } },
],
},
});
  • Use the tiles URLs from the TileJSON. They are absolute URLs. The host name can differ from the TileJSON host. Do not replace it yourself.
  • When a vector tile (.pbf) has no data, the response is 204 (no content), which is a different status from 404. MapLibre skips it.
  • Some vector tiles are returned with Content-Encoding: gzip. Browsers and MapLibre decompress them. Other clients must handle it themselves (add --compressed to curl).
  • Terrain tiles are 512 × 512. Set tileSize: 512 on a MapLibre raster-dem source.
  • Zoom range and coverage follow the TileJSON response. The excerpts on this page can differ from the live values.
  • Responses have no Cache-Control. These tiles rarely change, so you can cache them on the client.