Web (Node.js) Examples
Three examples showing how to integrate the Geog API with popular web mapping libraries using a plain Node.js server. Each example renders a vector tile basemap and adds places search with markers.
- MapLibre GL JS — WebGL-powered vector map with
transformRequestfor auth - Leaflet — Classic Leaflet API with a
maplibre-gl-leafletbridge for vector rendering - OpenLayers — Full-featured map framework with a custom
tileLoadFunctionfor auth
Prerequisites
- Node.js v18+
- A Geog API key (create one in the console)
Quick Start
Each web example follows the same steps. Replace maplibre with leaflet or openlayers as needed.
git clone https://github.com/geogdev/examples.git
cd examples/web/maplibre
npm install
cp .env.example .env
Add your API key to .env:
GEOG_API_KEY=your-api-key-here
Start the server:
npm start
Open http://localhost:3000.
Project Structure
All three web examples share the same file layout:
| File | Description |
|---|---|
server.js | Node.js HTTP server with token proxy (/api/geog-token) and places proxy (/api/places/search) |
lib/geog-client.js | API client — handles token exchange and caching at 80% TTL |
public/index.html | Map container and search UI |
public/app.js | Client-side map initialization and search logic |
public/style.css | Minimal styling |
.env.example | Environment variable template |
How It Works
Token Proxy
The server keeps the long-lived API key on the backend and exposes two proxy endpoints:
GET /api/geog-token— returns a cached short-lived access token (exchanges with the Geog API when the cache is stale)POST /api/places/search— forwards search requests to the Geog API with server-side authentication
The frontend never sees the long-lived API key.
Auth Injection by Library
Each library has a different mechanism for attaching the access token to tile requests:
MapLibre GL JS — uses transformRequest to intercept outgoing requests:
const map = new maplibregl.Map({
transformRequest: (url) => {
if (url.startsWith("https://api.geog.dev")) {
return {
url,
headers: { Authorization: `Bearer ${accessToken}` },
};
}
},
// ...
});
Leaflet — uses the maplibre-gl-leaflet bridge, which wraps MapLibre's WebGL renderer inside a Leaflet layer. Auth is handled through the bridge's transformRequest:
L.maplibreGL({
style: {
version: 8,
sources: {
geog: {
type: "vector",
tiles: [`https://api.geog.dev/v1/tiles/basemap/{z}/{x}/{y}.mvt`],
maxzoom: 14,
},
},
layers: [/* ... */],
},
transformRequest: (url) => {
if (url.startsWith("https://api.geog.dev")) {
return { url, headers: { Authorization: `Bearer ${accessToken}` } };
}
},
}).addTo(map);
OpenLayers — uses a custom tileLoadFunction since OL doesn't have a global request interceptor:
new VectorTileLayer({
source: new VectorTileSource({
tileLoadFunction: function (tile, url) {
tile.setLoader(function (extent, resolution, projection) {
fetch(url, {
headers: { Authorization: "Bearer " + accessToken },
})
.then((response) => response.arrayBuffer())
.then((data) => {
const features = format.readFeatures(data, { extent, featureProjection: projection });
tile.setFeatures(features);
});
});
},
// ...
}),
});
Full Source
See Also
- Examples Overview — All examples and the integration pattern
- Token Exchange API — Endpoint specification
- Vector Tiles API — Tile endpoint reference
- Places API — Search endpoint reference
- Styles & Sprites — Hosted themes, sprites, and npm packages