Angular Example
An Angular 19 application with standalone components that renders a MapLibre vector tile map and adds places search. Uses a companion Node.js server for token exchange.
Prerequisites
- Node.js v18+
- A Geog API key (create one in the console)
Quick Start
git clone https://github.com/geogdev/examples.git
cd examples/frameworks/angular-maplibre
npm install
cp .env.example .env
Add your API key to .env:
GEOG_API_KEY=your-api-key-here
Start both processes — the token proxy server and the Angular dev server:
# Terminal 1: Token proxy server (port 3001)
node server.js
# Terminal 2: Angular dev server (port 4200)
npm start
Open http://localhost:4200.
Project Structure
| File | Description |
|---|---|
server.js | Companion Node.js server (port 3001) — token exchange and places search proxy |
proxy.conf.json | Dev server proxy config — routes /api/* from port 4200 to port 3001 |
src/app/services/geog.service.ts | Injectable service — manages token cache and places search |
src/app/components/map/map.component.ts | Standalone component — MapLibre map with auth |
src/app/components/places-search/places-search.component.ts | Standalone component — search UI and markers |
.env.example | Environment variable template |
How It Works
Two-Process Dev Setup
Angular's dev server runs on port 4200. A companion Node.js server on port 3001 handles the token proxy. The proxy.conf.json file routes /api/* requests from the Angular dev server to the companion server:
{
"/api": {
"target": "http://localhost:3001",
"secure": false,
"changeOrigin": true
}
}
Injectable Service
GeogService is an Angular injectable that manages the token lifecycle and exposes methods for the map and search components:
@Injectable({ providedIn: "root" })
export class GeogService {
private cachedToken: string | null = null;
private tokenExpiresAt = 0;
async getToken(): Promise<string> {
const now = Date.now();
if (this.cachedToken && now < this.tokenExpiresAt) {
return this.cachedToken;
}
const response = await fetch("/api/geog-token");
const data = await response.json();
this.cachedToken = data.access_token;
this.tokenExpiresAt = now + data.expires_in * 1000 * 0.8;
return this.cachedToken;
}
async searchPlaces(query: string, lat: number, lon: number) {
// ...
}
}
Standalone Components
All components use standalone: true (no NgModules). The map component injects GeogService and initializes MapLibre in ngAfterViewInit with transformRequest for auth.
Full Source
github.com/geogdev/examples/tree/main/frameworks/angular-maplibre
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