Map Styles
ng-mapcn renders any MapLibre-compatible basemap. Carto is the default; here is a working example for each major provider.
Pass a per-theme styles config to a single map, or call provideMapStyles() once to set the basemap for the whole app — that is exactly what the basemap picker in this site's header does, so every map below (and on every other page) follows it live.
Carto (default)
# Used when no styles is given: Positron for light, Dark Matter for dark. No API key. Other variants: voyager-gl-style and the *-nolabels-* styles — this preview uses Voyager.
<!-- No [styles] input: Carto Positron (light) / Dark Matter (dark) -->
<ng-map [center]="[2.3522, 48.8566]" [zoom]="11" />
<!-- Other Carto variants, passed explicitly -->
<ng-map
[styles]="{
light: 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json',
dark: 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json'
}"
/>OpenFreeMap
# Free vector tiles built from OpenStreetMap data — no registration, no API key, no request limits. Styles: liberty, bright, positron, dark, fiord.
import { Component } from '@angular/core';
import { MapComponent, MapStylesConfig } from 'ng-mapcn';
@Component({
selector: 'app-openfreemap',
standalone: true,
imports: [MapComponent],
template: `
<div class="h-[420px]">
<ng-map [center]="[13.388, 52.517]" [zoom]="11" [styles]="styles" />
</div>
`,
})
export class OpenFreeMapComponent {
// No key, no registration, no request limits.
// Styles: liberty | bright | positron | dark | fiord
readonly styles: MapStylesConfig = {
light: 'https://tiles.openfreemap.org/styles/positron',
dark: 'https://tiles.openfreemap.org/styles/dark',
};
}OpenStreetMap
# OSM does not host a style.json — it serves raster tiles, so the MapLibre style is written by hand. Keep the object in a constant: the map compares the resolved style by identity before calling setStyle. The public tile server is for development and small demos only — read the tile usage policy before shipping it (OpenFreeMap is the drop-in alternative).
import { Component } from '@angular/core';
import type { StyleSpecification } from 'maplibre-gl';
import { MapComponent, MapStylesConfig } from 'ng-mapcn';
// OpenStreetMap serves raster tiles, not a hosted style.json — build the
// MapLibre style by hand. Keep it as a constant: ng-map compares the resolved
// style by identity before calling setStyle().
const OSM_STYLE: StyleSpecification = {
version: 8,
sources: {
osm: {
type: 'raster',
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
maxzoom: 19,
attribution: '© OpenStreetMap contributors',
},
},
layers: [{ id: 'osm', type: 'raster', source: 'osm' }],
};
@Component({
selector: 'app-osm-map',
standalone: true,
imports: [MapComponent],
template: `
<div class="h-[420px]">
<ng-map [center]="[-0.1276, 51.5074]" [zoom]="12" [styles]="styles" />
</div>
`,
})
export class OsmMapComponent {
// Raster has no dark variant — same style for both themes.
readonly styles: MapStylesConfig = { light: OSM_STYLE, dark: OSM_STYLE };
}MapTiler
# Requires an API key (?key=). Style ids follow the streets-v4 / streets-v4-dark pattern (also dataviz-v4, satellite). To preview it live, pick MapTiler in the header and paste your key — it is kept in your browser only.
import { Component } from '@angular/core';
import { MapComponent, MapStylesConfig } from 'ng-mapcn';
@Component({
selector: 'app-maptiler-map',
standalone: true,
imports: [MapComponent],
template: `
<div class="h-[420px]">
<ng-map [center]="[-46.633, -23.55]" [zoom]="11" [styles]="styles" />
</div>
`,
})
export class MapTilerMapComponent {
// Get a key at https://cloud.maptiler.com/account/keys/
// Style ids: streets-v4, streets-v4-dark, dataviz-v4, dataviz-v4-dark,
// satellite, outdoor-v2, ... (v2 ids still work)
private readonly key = 'YOUR_MAPTILER_KEY';
readonly styles: MapStylesConfig = {
light: `https://api.maptiler.com/maps/streets-v4/style.json?key=${this.key}`,
dark: `https://api.maptiler.com/maps/streets-v4-dark/style.json?key=${this.key}`,
};
}Stadia Maps
# Keyless on localhost (rate limited); in production use ?api_key= or domain-based auth. Styles: alidade_smooth, alidade_smooth_dark, outdoors, osm_bright.
import { Component } from '@angular/core';
import { MapComponent, MapStylesConfig } from 'ng-mapcn';
@Component({
selector: 'app-stadia-map',
standalone: true,
imports: [MapComponent],
template: `
<div class="h-[420px]">
<ng-map [center]="[12, 53]" [zoom]="5" [styles]="styles" />
</div>
`,
})
export class StadiaMapComponent {
// On localhost / 127.0.0.1 the key is optional (rate limited). In production
// use an API key or domain-based auth: https://client.stadiamaps.com/
// Styles: alidade_smooth, alidade_smooth_dark, outdoors, osm_bright, stamen_*
private readonly auth = '?api_key=YOUR_STADIA_KEY';
readonly styles: MapStylesConfig = {
light: `https://tiles.stadiamaps.com/styles/alidade_smooth.json${this.auth}`,
dark: `https://tiles.stadiamaps.com/styles/alidade_smooth_dark.json${this.auth}`,
};
}App-wide basemap
#provideMapStyles() sets the default basemap for every ng-map in the app. Precedence: [styles] → [blank] → provideMapStyles() → Carto. Pass a signal and the basemap swaps at runtime — the header picker on this site is that signal.
// basemap.service.ts — one signal holding the app's basemap
import { computed, Injectable, signal } from '@angular/core';
import { MapStylesConfig } from 'ng-mapcn';
@Injectable({ providedIn: 'root' })
export class BasemapService {
readonly provider = signal<'carto' | 'openfreemap'>('carto');
readonly styles = computed<MapStylesConfig | undefined>(() =>
this.provider() === 'openfreemap'
? {
light: 'https://tiles.openfreemap.org/styles/positron',
dark: 'https://tiles.openfreemap.org/styles/dark',
}
: undefined, // undefined = built-in Carto defaults
);
}
// app.config.ts
import { inject } from '@angular/core';
import { provideMapStyles } from 'ng-mapcn';
export const appConfig: ApplicationConfig = {
providers: [
// Also accepts a plain config: provideMapStyles({ light, dark })
provideMapStyles(() => inject(BasemapService).styles),
],
};