Viewport Places Plugin

The Viewport Places plugin enables dynamic display of places on the map viewport, automatically updating as the map moves. It wires the SDK search service to the SDK PlacesModule and provides a small, composable API to manage multiple viewport-driven place layers.

import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
import { TomTomMap } from '@tomtom-org/maps-sdk/map';
import { ViewportPlaces } from '@tomtom-org/maps-sdk-plugin-viewport-places';
import './style.css';
import { API_KEY } from './config';

// (Set your own API key when working in your own environment)
TomTomConfig.instance.put({ apiKey: API_KEY, language: 'en-GB' });

(async () => {
    const map = new TomTomMap({
        mapLibre: { container: 'sdk-map', center: [4.9041, 52.3676], zoom: 14 },
    });

    const placesLayers = new ViewportPlaces(map);
    await placesLayers.addPOICategories({
        minZoom: 12,
        categories: ['PARKING_GARAGE', 'OPEN_PARKING_AREA', 'ELECTRIC_VEHICLE_STATION'],
    });
    // These categories will show up on top of (higher priority) the previous ones:
    await placesLayers.addPOICategories({
        minZoom: 10,
        categories: ['SUPERMARKETS_HYPERMARKETS'],
    });
    await placesLayers.add({
        minZoom: 8,
        searchOptions: { query: 'Lidl', poiCategories: ['SUPERMARKETS_HYPERMARKETS'], limit: 20 },
        placesModuleConfig: { theme: 'pin' },
    });
})();

Use cases

  • Customize your map POIs — control which POI categories are shown at which zoom levels and with which visual theme.
  • Search this area — keep search results (fuzzy/geometry) limited to the current viewport and refresh them automatically when the user pans or zooms.
  • Layered overlays — stack multiple place modules (base-map POIs, brand search results, availability overlays) and control their priority.

How it works

Each time the map moves, the plugins queries the search service for places within the current viewport bounding box and displays them using a dedicated PlacesModule.

This can be done for multiple place modules, each with its own search options (query string, POI categories, limits) and visual configuration (theme, clustering, etc).

API Reference:

Viewport Places Plugin API Reference

Guides to the underlying components

Installation

All plugins use @tomtom-org/maps-sdk as a peer dependency — ensure the SDK is installed in your project.

  1. Follow the SDK Project Setup to create a working SDK project and initialize a TomTomMap instance.

  2. Import and initialize the plugin (plugin-specific steps only):

// assume `map` is your initialized TomTomMap instance
// import the plugin in your application code:
// import { ViewportPlaces } from '@tomtom-org/maps-sdk-plugin-viewport-places';
const viewportPlaces = new ViewportPlaces(map);
  1. Try it: add a simple viewport-driven place module:
await viewportPlaces.addBaseMapPOICategories({
id: 'restaurants',
categories: ['RESTAURANT'],
minZoom: 10
});

The plugin will keep the restaurants place module in sync with the visible map bounds.

Place modules are rendered bottom-up in the order they are added: the first added module is displayed at the bottom, and later modules are stacked on top.

For a complete working example, see the viewport-places-plugin example in the SDK repository (live coding example above).

Usage examples

Add base-map POI categories (styled like the base map)

Use when you want to surface additional base map categories or override visibility at specific zooms:

await viewportPlaces.addBaseMapPOICategories({
id: 'base-pois',
categories: ['PARKING_GARAGE', 'ELECTRIC_VEHICLE_STATION'],
minZoom: 10
});

Add a branded search place module (custom theme)

Use placesModuleConfig to apply a visual theme (for example pin vs base-map):

await viewportPlaces.add({
id: 'brand-search',
searchOptions: { query: 'Lidl', poiCategories: ['SUPERMARKETS_HYPERMARKETS'], limit: 20 },
minZoom: 8,
placesModuleConfig: { theme: 'pin' }
});

Update an existing place module

Change query, categories, limits or visual config for an existing place module:

await viewportPlaces.update({
id: 'brand-search',
searchOptions: { query: 'Aldi', limit: 30 },
placesModuleConfig: { theme: 'base-map' }
});

Remove a place module

viewportPlaces.remove('brand-search');

Remove all place modules

viewportPlaces.removeAll();