MCPInstall

syncfusion-javascript-maps

Guide to implementing Syncfusion Maps in TypeScript and JavaScript. Use this skill whenever the user needs to create interactive maps, add markers, visualize geographical data, work with map layers, apply color mapping, add annotations, configure legends, or handle map interactions and events. Works with TypeScript (module-based) and JavaScript (CDN/ES5).

Installs
63
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/syncfusion/javascript-ui-controls-skills --skill syncfusion-javascript-maps
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads syncfusion-javascript-maps automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Implementing Syncfusion Maps in TypeScript and JavaScript

The Syncfusion EJ2 Maps component visualizes geographic information through online tile providers, GeoJSON shape layers, markers, bubbles, custom polygons, navigation lines, labels, legends, annotations, tooltips, selection, zooming, panning, printing, and exporting.

This skill covers framework-neutral implementations for:

  • TypeScript applications using npm and module imports.
  • JavaScript applications using a versioned EJ2 global bundle.
  • OpenStreetMap and authenticated map providers.
  • GeoJSON geographic shapes.
  • Coordinate-based markers.
  • Region-bound bubbles.
  • Custom polygon overlays.
  • Shape and bubble color mapping.
  • Navigation lines.
  • Legends, annotations, and tooltips.
  • Selection and highlighting.
  • Built-in and application-owned persistence.
  • Printing and image export.
  • Accessibility, validation, performance, and cleanup.

Platform Support

TypeScript

Use TypeScript when the application uses:

  • The @syncfusion/ej2-maps npm package.
  • TypeScript compilation.
  • Webpack, Vite, or another module bundler.
  • Explicit feature-module injection.
  • Strongly typed data and configuration models.
  • Compile-time validation and IDE IntelliSense.

Install the package:

npm install @syncfusion/ej2-maps

Basic import:

import {
    Maps
} from '@syncfusion/ej2-maps';

Feature modules must be imported and injected before constructing Maps.

import {
    Maps,
    Marker,
    Zoom
} from '@syncfusion/ej2-maps';

Maps.Inject(
    Zoom,
    Marker
);

JavaScript

Use global JavaScript when the application uses:

  • A versioned EJ2 CDN bundle.
  • A locally hosted EJ2 global bundle.
  • Traditional HTML and JavaScript files.
  • The global ej.maps.Maps constructor.
  • No TypeScript compilation.

Global constructor:

ej.maps.Maps

Use the complete versioned EJ2 global bundle:

<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js"></script>

Do not mix the complete bundle with separate ej2-base, ej2-data, ej2-svg-base, and ej2-maps scripts.

Global JavaScript using the complete bundle does not require explicit Maps.Inject(...) calls.

JavaScript Compatibility

The global JavaScript examples use ES5-compatible syntax where practical:

var declarations
Traditional functions
No TypeScript annotations
No ECMAScript module imports
Global ej namespace

Browser support must still match the supported-browser matrix of the installed EJ2 release.

Do not promise unrestricted legacy-browser compatibility.

When to Use This Skill

Use this skill when the task requires:

  • Rendering an online map provider.
  • Rendering countries, states, or custom regions from GeoJSON.
  • Displaying coordinate-based locations.
  • Visualizing regional magnitude with bubbles.
  • Applying data-driven shape or bubble colors.
  • Drawing custom coordinate-defined polygon areas.
  • Connecting locations with navigation lines.
  • Adding data labels to geographic shapes.
  • Displaying legends and tooltips.
  • Adding map-relative annotation content.
  • Selecting or highlighting shapes, markers, or bubbles.
  • Supporting zooming and panning.
  • Persisting supported map state.
  • Storing validated application preferences.
  • Printing the rendered map.
  • Exporting the map as PNG, JPEG, or SVG.
  • Supporting responsive layouts.
  • Optimizing large geographic datasets.
  • Diagnosing setup, network, data-binding, or rendering failures.

Visualization Selection Guide

Use Markers

Use markers for locations defined directly by latitude and longitude.

Examples:

  • Offices.
  • Stores.
  • Airports.
  • Warehouses.
  • Incident points.
  • Route waypoints.

Use Bubbles

Use bubbles for numeric values associated with GeoJSON shapes.

Examples:

  • Population by country.
  • Revenue by state.
  • Sales by territory.
  • Engagement by region.

Bubbles are not direct replacements for coordinate markers.

Use GeoJSON Shapes

Use shapeData for:

  • Countries.
  • States.
  • Provinces.
  • Districts.
  • Administrative boundaries.
  • Custom geographic feature collections.

Use Custom Polygons

Use polygonSettings.polygons for application-defined areas based on coordinate points.

Examples:

  • Delivery zones.
  • Restricted regions.
  • Coverage areas.
  • Service boundaries.

Use Navigation Lines

Use navigation lines to display:

  • Routes.
  • Journeys.
  • Connections.
  • Flight paths.
  • Geographic dependencies.

Feature Module Reference

Zooming and panning -> Zoom
Markers             -> Marker
Bubbles             -> Bubble
Navigation lines    -> NavigationLine
Tooltips            -> MapsTooltip
Legends             -> Legend
Annotations         -> Annotations
Selection           -> Selection
Data labels         -> DataLabel
Custom polygons     -> Polygon
Printing            -> Print
Image export        -> ImageExport
PDF export          -> PdfExport

Import and inject only the modules used by an example.

Example:

import {
    Maps,
    MapsTooltip,
    Marker,
    Zoom
} from '@syncfusion/ej2-maps';

Maps.Inject(
    Zoom,
    Marker,
    MapsTooltip
);

Keep imports and injection synchronized.

Incorrect:

import {
    Maps
} from '@syncfusion/ej2-maps';

Maps.Inject(
    Marker
);

Correct:

import {
    Maps,
    Marker
} from '@syncfusion/ej2-maps';

Maps.Inject(
    Marker
);

Implementation Rules

Use Explicit DOM Attachment

Preferred TypeScript:

const map: Maps =
    new Maps({
        layers
    });

map.appendTo(
    '#maps-container'
);

Preferred JavaScript:

var map =
    new ej.maps.Maps({
        layers: layers
    });

map.appendTo(
    '#maps-container'
);

Verify the Host Element

const host:
    HTMLElement | null =
        document.getElementById(
            'maps-container'
        );

if (!host) {
    throw new Error(
        'The Maps host element "#maps-container" was not found.'
    );
}

Provide Measurable Dimensions

#maps-container {
    width: 100%;
    min-height: 600px;
}

Configure Maps with a definite height:

width:
    '100%',

height:
    '600px'

Avoid relying on:

height:
    '100%'

unless every relevant ancestor has a definite computed height.

Use centerPosition

Incorrect:

center: {
    latitude: 37.7749,
    longitude: -122.4194
}

Correct:

centerPosition: {
    latitude: 37.7749,
    longitude: -122.4194
}

Keep Feature Configuration at the Correct Level

Shape data             -> Layer shapeData
Shape binding data     -> Layer dataSource
Shape tooltip          -> Layer tooltipSettings
Shape selection        -> Layer selectionSettings
Markers                -> Layer markerSettings array
Marker tooltip          -> Marker entry tooltipSettings
Marker selection        -> Marker entry selectionSettings
Bubbles                -> Layer bubbleSettings array
Bubble tooltip          -> Bubble entry tooltipSettings
Bubble selection        -> Bubble entry selectionSettings
Navigation lines       -> Layer navigationLineSettings array
Custom polygons        -> Layer polygonSettings
Shape labels           -> Layer dataLabelSettings

Documentation and Navigation Guide

Getting Started and Setup

Read:

references/getting-started.md

Use this reference for:

  • Package installation.
  • TypeScript imports.
  • Module injection.
  • JavaScript CDN setup.
  • OpenStreetMap initialization.
  • Host dimensions.
  • World-map data acquisition.
  • First Maps implementation.

Data and Layers

Read:

references/data-and-layers.md

Use this reference for:

  • Online tile layers.
  • GeoJSON shape layers.
  • Main layers.
  • Sublayers.
  • baseLayerIndex.
  • Shape data binding.
  • Marker and bubble data placement.
  • Layer visibility.
  • Safe runtime updates.

Markers and Navigation

Read:

references/markers-and-navigation.md

Use this reference for:

  • Coordinate-based markers.
  • Marker appearance.
  • Marker templates.
  • Marker images.
  • Marker tooltips.
  • Marker selection.
  • Marker events.
  • Marker clustering.
  • Navigation lines.
  • Dynamic marker and route updates.

Visualization Features

Read:

references/visualization-features.md

Use this reference for:

  • Region-bound bubbles.
  • GeoJSON shape rendering.
  • Custom polygon overlays.
  • Shape color mapping.
  • Bubble color mapping.
  • Shape data labels.
  • Combined regional visualizations.

Legends and Annotations

Read:

references/legends-and-annotations.md

Use this reference for:

  • Default and Interactive legends.
  • Docked and floating legends.
  • Layer, marker, and bubble legends.
  • Legend toggle behavior.
  • Map-relative annotations.
  • Shape, marker, and bubble tooltips.

Map Providers and Selection

Read:

references/map-providers-and-selection.md

Use this reference for:

  • OpenStreetMap.
  • Bing Maps.
  • Custom tile providers.
  • Provider authentication.
  • Provider security and attribution.
  • Shape selection.
  • Marker selection.
  • Bubble selection.
  • Single and multiple selection.
  • Validated interaction events.

Customization and Persistence

Read:

references/customization-and-persistence.md

Use this reference for:

  • Built-in themes.
  • Public appearance models.
  • Application-owned wrapper CSS.
  • Responsive layouts.
  • Built-in persistence.
  • Validated browser-storage preferences.
  • Printing.
  • PNG, JPEG, and SVG export.
  • Cleanup.

Troubleshooting

Read:

references/troubleshooting.md

Use this reference for:

  • Installation failures.
  • Bundle-loading failures.
  • Missing module injection.
  • Host and dimension problems.
  • Tile-provider failures.
  • GeoJSON loading failures.
  • Marker and bubble issues.
  • Data-binding problems.
  • Color-mapping failures.
  • Tooltip and selection issues.
  • Performance and memory problems.
  • TypeScript and JavaScript diagnostics.

TypeScript Quick Start

This example renders OpenStreetMap with a marker, marker tooltip, zooming, and panning.

index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">

    <meta
        name="viewport"
        content="width=device-width, initial-scale=1.0"
    >

    <title>Syncfusion Maps</title>

    ./styles.css
</head>

<body>
    <main class="page-container">
        <section
            class="maps-card"
            aria-labelledby="maps-heading"
            aria-describedby="maps-description"
        >
            <h1 id="maps-heading">
                Office Location
            </h1>

            <p id="maps-description">
                An interactive OpenStreetMap view showing the
                San Francisco office location.
            </p>

            <div id="maps-container"></div>

            <p class="map-attribution">
                Map data © OpenStreetMap contributors
            </p>

            <p
                id="maps-status"
                aria-live="polite"
            >
                Loading the map.
            </p>
        </section>
    </main>

    <script scr="app.ts"></script>
</body>
</html>

styles.css

html,
body {
    margin: 0;
    min-height: 100%;
}

body {
    color: #111827;
    background: #f1f5f9;
    font-family:
        "Segoe UI",
        Arial,
        sans-serif;
}

.page-container {
    width: 100%;
    min-height: 100vh;
    padding: 24px;
    box-sizing: border-box;
}

.maps-card {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 16px;
    box-sizing: border-box;
    background: #ffffff;
    border: 1px solid #cbd5e1;
    border-radius: 8px;
}

.maps-card h1 {
    margin: 0 0 8px;
    font-size: 24px;
}

.maps-card > p {
    color: #475569;
    line-height: 1.5;
}

#maps-container {
    width: 100%;
    min-height: 600px;
}

.map-attribution {
    margin: 8px 0 0;
    font-size: 12px;
}

@media (max-width: 768px) {
    .page-container {
        padding: 12px;
    }

    .maps-card {
        padding: 12px;
    }

    #maps-container {
        min-height: 500px;
    }
}

app.ts

import {
    Maps,
    MapsTooltip,
    Marker,
    Zoom
} from '@syncfusion/ej2-maps';

Maps.Inject(
    Zoom,
    Marker,
    MapsTooltip
);

interface LocationData {
    id: string;
    name: string;
    latitude: number;
    longitude: number;
}

const locationData:
    LocationData[] = [
        {
            id:
                'san-francisco-office',
            name:
                'San Francisco Office',
            latitude:
                37.7749,
            longitude:
                -122.4194
        }
    ];

const validateLocations = (
    locations:
        LocationData[]
): void => {
    const ids:
        Set<string> =
            new Set<string>();

    locations.forEach(
        (
            location:
                LocationData
        ): void => {
            if (
                !location.id.trim()
            ) {
                throw new Error(
                    'Every marker requires a nonempty ID.'
                );
            }

            if (
                ids.has(
                    location.id
                )
            ) {
                throw new Error(
                    'Duplicate marker ID: ' +
                    location.id
                );
            }

            if (
                !location.name.trim()
            ) {
                throw new Error(
                    'Every marker requires a name.'
                );
            }

            if (
                !Number.isFinite(
                    location.latitude
                ) ||
                location.latitude < -90 ||
                location.latitude > 90
            ) {
                throw new Error(
                    'Invalid marker latitude.'
                );
            }

            if (
                !Number.isFinite(
                    location.longitude
                ) ||
                location.longitude < -180 ||
                location.longitude > 180
            ) {
                throw new Error(
                    'Invalid marker longitude.'
                );
            }

            ids.add(
                location.id
            );
        }
    );
};

validateLocations(
    locationData
);

const host:
    HTMLElement | null =
        document.getElementById(
            'maps-container'
        );

const statusElement:
    HTMLElement | null =
        document.getElementById(
            'maps-status'
        );

if (!host) {
    throw new Error(
        'The Maps host element "#maps-container" was not found.'
    );
}

const map: Maps =
    new Maps({
        width: '100%',
        height: '600px',

        centerPosition: {
            latitude: 37.7749,
            longitude: -122.4194
        },

        zoomSettings: {
            enable: true,
            enablePanning: true,
            mouseWheelZoom: true,
            pinchZooming: true,
            minZoom: 1,
            maxZoom: 13,
            zoomFactor: 5,

            toolbarSettings: {
                buttonSettings: {
                    toolbarItems: [
                        'Zoom',
                        'ZoomIn',
                        'ZoomOut',
                        'Pan',
                        'Reset'
                    ]
                }
            }
        },

        layers: [
            {
                urlTemplate:
                    'https://tile.openstreetmap.org/level/tileX/tileY.png',

                markerSettings: [
                    {
                        visible: true,
                        dataSource:
                            locationData,
                        latitudeValuePath:
                            'latitude',
                        longitudeValuePath:
                            'longitude',
                        width: 24,
                        height: 24,
                        shape: 'Circle',
                        fill: '#dc2626',

                        border: {
                            color: '#ffffff',
                            width: 2
                        },

                        tooltipSettings: {
                            visible: true,
                            valuePath:
                                'name'
                        }
                    }
                ]
            }
        ],

        loaded: (): void => {
            if (
                statusElement
            ) {
                statusElement.textContent =
                    'The map loaded successfully.';
            }
        }
    });

map.appendTo(
    host
);

JavaScript Quick Start

This example provides equivalent behavior in one standalone HTML file.

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">

    <meta
        name="viewport"
        content="width=device-width, initial-scale=1.0"
    >

    <title>Syncfusion Maps</title>


    <style>
        html,
        body {
            margin: 0;
            min-height: 100%;
        }

        body {
            color: #111827;
            background: #f1f5f9;
            font-family:
                "Segoe UI",
                Arial,
                sans-serif;
        }

        .page-container {
            width: 100%;
            min-height: 100vh;
            padding: 24px;
            box-sizing: border-box;
        }

        .maps-card {
            width: 100%;
            max-width: 1200px;
            margin: 0 auto;
            padding: 16px;
            box-sizing: border-box;
            background: #ffffff;
            border: 1px solid #cbd5e1;
            border-radius: 8px;
        }

        #maps-container {
            width: 100%;
            min-height: 600px;
        }

        .map-attribution {
            color: #475569;
            font-size: 12px;
        }

        @media (max-width: 768px) {
            .page-container {
                padding: 12px;
            }

            #maps-container {
                min-height: 500px;
            }
        }
    </style>
    <script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js"></script>
</head>

<body>
    <main class="page-container">
        <section
            class="maps-card"
            aria-labelledby="maps-heading"
            aria-describedby="maps-description"
        >
            <h1 id="maps-heading">
                Office Location
            </h1>

            <p id="maps-description">
                An interactive OpenStreetMap view showing the
                San Francisco office location.
            </p>

            <div id="maps-container"></div>

            <p class="map-attribution">
                Map data © OpenStreetMap contributors
            </p>

            <p
                id="maps-status"
                aria-live="polite"
            >
                Loading the map.
            </p>
        </section>
    </main>

    <script>
        var locationData = [
            {
                id:
                    'san-francisco-office',
                name:
                    'San Francisco Office',
                latitude:
                    37.7749,
                longitude:
                    -122.4194
            }
        ];

        function validateLocations(
            locations
        ) {
            var ids =
                new Set();

            locations.forEach(
                function (location) {
                    if (
                        typeof location.id !==
                            'string' ||
                        location.id
                            .trim()
                            .length === 0
                    ) {
                        throw new Error(
                            'Every marker requires a nonempty ID.'
                        );
                    }

                    if (
                        ids.has(
                            location.id
                        )
                    ) {
                        throw new Error(
                            'Duplicate marker ID: ' +
                            location.id
                        );
                    }

                    if (
                        !Number.isFinite(
                            location.latitude
                        ) ||
                        location.latitude < -90 ||
                        location.latitude > 90
                    ) {
                        throw new Error(
                            'Invalid marker latitude.'
                        );
                    }

                    if (
                        !Number.isFinite(
                            location.longitude
                        ) ||
                        location.longitude < -180 ||
                        location.longitude > 180
                    ) {
                        throw new Error(
                            'Invalid marker longitude.'
                        );
                    }

                    ids.add(
                        location.id
                    );
                }
            );
        }

        validateLocations(
            locationData
        );

        var host =
            document.getElementById(
                'maps-container'
            );

        var statusElement =
            document.getElementById(
                'maps-status'
            );

        if (!host) {
            throw new Error(
                'The Maps host element "#maps-container" was not found.'
            );
        }

        if (
            typeof window.ej ===
                'undefined' ||
            !window.ej.maps
        ) {
            throw new Error(
                'The EJ2 Maps global bundle was not loaded.'
            );
        }

        var map =
            new ej.maps.Maps({
                width: '100%',
                height: '600px',

                centerPosition: {
                    latitude: 37.7749,
                    longitude: -122.4194
                },

                zoomSettings: {
                    enable: true,
                    enablePanning: true,
                    mouseWheelZoom: true,
                    pinchZooming: true,
                    minZoom: 1,
                    maxZoom: 13,
                    zoomFactor: 5,

                    toolbarSettings: {
                        buttonSettings: {
                            toolbarItems: [
                                'Zoom',
                                'ZoomIn',
                                'ZoomOut',
                                'Pan',
                                'Reset'
                            ]
                        }
                    }
                },

                layers: [
                    {
                        urlTemplate:
                            'https://tile.openstreetmap.org/level/tileX/tileY.png',

                        markerSettings: [
                            {
                                visible: true,
                                dataSource:
                                    locationData,
                                latitudeValuePath:
                                    'latitude',
                                longitudeValuePath:
                                    'longitude',
                                width: 24,
                                height: 24,
                                shape: 'Circle',
                                fill: '#dc2626',

                                border: {
                                    color:
                                        '#ffffff',
                                    width: 2
                                },

                                tooltipSettings: {
                                    visible: true,
                                    valuePath:
                                        'name'
                                }
                            }
                        ]
                    }
                ],

                loaded:
                    function () {
                        statusElement.textContent =
                            'The map loaded successfully.';
                    }
            });

        map.appendTo(
            host
        );
    </script>
</body>
</html>

GeoJSON World Map Setup

OpenStreetMap does not require a world-map file.

GeoJSON shape, color-mapping, shape-label, and bubble examples require complete shapeData.

Download a world-map GeoJSON file:

mkdir -p src/data
curl -L "https://datahub.io/core/geo-countries/_r/-/data/countries.geojson" -o "src/data/world-map.geojson"

Manual download:

https://datahub.io/core/geo-countries/_r/-/data/countries.geojson

Validate it:

import {
    readFile
} from 'node:fs/promises';

const content =
    await readFile(
        'src/data/world-map.geojson',
        'utf8'
    );

const worldMap =
    JSON.parse(
        content
    );

if (
    worldMap.type !==
    'FeatureCollection'
) {
    throw new Error(
        'The world-map file must be a GeoJSON FeatureCollection.'
    );
}

if (
    !Array.isArray(
        worldMap.features
    ) ||
    worldMap.features.length === 0
) {
    throw new Error(
        'The world-map file does not contain features.'
    );
}

For TypeScript JSON imports, enable:

{
  "compilerOptions": {
    "resolveJsonModule": true,
    "esModuleInterop": true
  }
}

Then import:

import worldMap
    from './data/world-map.json';

Common Patterns

Regional Data Visualization

Use a GeoJSON layer with complete data binding.

layers: [
    {
        shapeData:
            worldMap,

        dataSource:
            regionData,

        shapePropertyPath:
            'name',

        shapeDataPath:
            'country',

        shapeSettings: {
            fill: '#e2e8f0',
            colorValuePath:
                'value',

            colorMapping: [
                {
                    from: 0,
                    to: 39,
                    color: '#dbeafe',
                    label: 'Low'
                },
                {
                    from: 40,
                    to: 69,
                    color: '#60a5fa',
                    label: 'Moderate'
                },
                {
                    from: 70,
                    to: 100,
                    color: '#1d4ed8',
                    label: 'High'
                }
            ]
        }
    }
]

Use singular:

colorMapping

Do not use:

colorMappings

Multi-Layer Maps

Use a validated main layer and SubLayer overlays.

layers: [
    {
        shapeData:
            worldMap
    },
    {
        type: 'SubLayer',
        shapeData:
            overlayGeoJson,

        shapeSettings: {
            fill:
                'rgb(37 99 235 / 30%)'
        }
    }
]

Do not create empty layers merely to separate marker and bubble configuration.

Interactive Experience

Use:

Zoom        -> Zooming and panning
MapsTooltip -> Tooltips
Selection   -> Visual selection

Keep click events and visual selection separate.

Use external persistent details when information is important. Do not rely only on hover tooltips.

Navigation and Route Visualization

navigationLineSettings: [
    {
        latitude: [
            37.7749,
            34.0522
        ],

        longitude: [
            -122.4194,
            -118.2437
        ],

        color: '#2563eb',
        width: 3,
        opacity: 0.8,
        dashArray: '8 4'
    }
]

Validate:

  • At least two coordinate pairs.
  • Matching latitude and longitude array lengths.
  • Finite coordinate values.
  • Latitude between -90 and 90.
  • Longitude between -180 and 180.
  • Positive line width.
  • Opacity between 0 and 1.

Distance and duration are application-owned values. Navigation lines do not automatically calculate route distance, travel duration, or road directions.

Key Features at a Glance

Markers

Use for geographic points based on latitude and longitude.

Bubbles

Use for magnitude visualization associated with GeoJSON shapes.

GeoJSON Shapes

Use for geographic boundaries supplied through shapeData.

Custom Polygons

Use for coordinate-defined overlays supplied through polygonSettings.polygons.

Color Mapping

Use range, equal-value, or opacity-based shape and bubble coloring.

Layers

Use main layers and validated SubLayer overlays.

Navigation Lines

Use coordinate paths to connect locations.

Legends

Use to explain layer, bubble, or marker colors and symbols.

Annotations

Use for map-relative HTML overlays positioned through x and y.

Annotations do not use latitude and longitude. Use markers for geographic points.

Tooltips

Use for contextual information associated with shapes, markers, or bubbles.

Persistence

Use enablePersistence when built-in component persistence meets the application requirement.

Use validated application-owned storage for custom preferences, schema versioning, expiration, layer visibility, or user-specific settings.

Print and Export

Use:

Print       -> Print module and allowPrint
ImageExport -> ImageExport module and allowImageExport
PdfExport   -> PdfExport module and allowPdfExport

Runtime Validation Checklist

✅ @syncfusion/ej2-maps is installed.
✅ Maps is imported.
✅ Every enabled TypeScript feature has its module imported.
✅ Every imported runtime module is injected before construction.
✅ Unused optional modules are not injected.
✅ Global JavaScript does not call Maps.Inject.
✅ The complete EJ2 bundle loads before application code.
✅ Combined and individual bundles are not mixed.
✅ Every CDN script URL ends in .min.js.
✅ The Maps host exists.
✅ The appendTo target matches the host ID.
✅ The host has measurable width and height.
✅ Maps width and height use valid CSS-size strings.
✅ centerPosition is used instead of center.
✅ Zoom is injected when zooming or panning is enabled.
✅ Tile URLs are plain strings.
✅ OpenStreetMap URLs contain level, tileX, and tileY.
✅ OpenStreetMap attribution is visible.
✅ Provider terms and network requirements are reviewed.
✅ Maps provider credentials are protected as far as the provider permits.
✅ The layer contains urlTemplate or shapeData.
✅ GeoJSON is a nonempty FeatureCollection.
✅ shapePropertyPath matches a GeoJSON feature property.
✅ shapeDataPath matches application data.
✅ markerSettings is an array.
✅ Every active marker entry uses visible: true.
✅ Marker coordinate paths match marker data.
✅ Marker IDs are nonempty and unique when required.
✅ Marker latitudes are finite and between -90 and 90.
✅ Marker longitudes are finite and between -180 and 180.
✅ bubbleSettings is an array.
✅ Every active bubble entry uses visible: true.
✅ Bubble data is associated with GeoJSON shapes.
✅ Bubble valuePath matches finite numeric values.
✅ colorMapping uses the singular property name.
✅ Color ranges are finite and nonoverlapping.
✅ Navigation-line coordinate arrays have matching lengths.
✅ Annotations use x and y rather than latitude and longitude.
✅ Layer indexes are validated before runtime updates.
✅ Storage preferences are validated before use.
✅ Print and export flags match injected modules.
✅ Runtime updates are batched.
✅ refresh is called once after complete updates.
✅ Important information is not communicated only by color, size, or hover.
✅ Application-owned listeners and timers are cleaned up.
✅ Pending requests are cancelled where appropriate.
✅ map.destroy() is called when a dynamic host is removed.
✅ No encoded HTML replaces executable markup.
✅ No rich-text anchors or editor-generated classes remain.

Accessibility Guidance

  • Provide a semantic heading.
  • Provide a concise map description.
  • Include meaningful marker and region names.
  • Do not rely only on marker color.
  • Do not rely only on bubble size.
  • Do not rely only on mapped shape color.
  • Provide descriptive legend labels.
  • Provide persistent selection details.
  • Preserve visible focus.
  • Use native buttons for print, export, reset, and other application actions.
  • Provide semantic tables for decision-critical visualization data.
  • Keep marker targets usable on touch devices.
  • Do not make tooltip content the only source of essential information.
  • Avoid excessive live-region announcements.
  • Include required provider attribution.
  • Test keyboard, touch, screen-reader, browser zoom, and reflow behavior.
  • Do not claim that the complete application is automatically compliant with an accessibility standard.

Performance and Cleanup

  • Reuse parsed GeoJSON.
  • Avoid repeatedly fetching unchanged shapes.
  • Simplify geometry only after validating geographic accuracy.
  • Validate marker, bubble, shape, and route data before rendering.
  • Keep marker and tooltip templates simple.
  • Use clustering only after profiling.
  • Batch runtime changes.
  • Call refresh() once.
  • Avoid expensive render-event logging.
  • Avoid recreating Maps in the same host without cleanup.
  • Remove application-owned event listeners.
  • Clear pending timers.
  • Cancel pending requests where appropriate.
  • Destroy Maps when its dynamic view is removed.
map.destroy();

Combined Mistakes and Future References

Incorrect Center Property

Incorrect:

center: {
    latitude: 37.7749,
    longitude: -122.4194
}

Correct:

centerPosition: {
    latitude: 37.7749,
    longitude: -122.4194
}

Missing Zoom Injection

Incorrect:

import {
    Maps
} from '@syncfusion/ej2-maps';

const map: Maps =
    new Maps({
        zoomSettings: {
            enable: true
        }
    });

Correct:

import {
    Maps,
    Zoom
} from '@syncfusion/ej2-maps';

Maps.Inject(
    Zoom
);

Marker Settings as an Object

Incorrect:

markerSettings: {
    dataSource:
        locationData
}

Correct:

markerSettings: [
    {
        visible: true,
        dataSource:
            locationData
    }
]

Bubble Settings as an Object

Incorrect:

bubbleSettings: {
    dataSource:
        bubbleData
}

Correct:

bubbleSettings: [
    {
        visible: true,
        dataSource:
            bubbleData
    }
]

Missing Feature Visibility

Incorrect:

markerSettings: [
    {
        dataSource:
            locationData
    }
]

Correct:

markerSettings: [
    {
        visible: true,
        dataSource:
            locationData
    }
]

Rich-Text Tile URL

Incorrect:

urlTemplate:
    'https://tile.openstreetmap.org/......</a>'

Correct:

urlTemplate:
    'https://tile.openstreetmap.org/level/tileX/tileY.png'

Unnecessary OSM Type

Avoid:

type:
    'OSM'

Use:

urlTemplate:
    'https://tile.openstreetmap.org/level/tileX/tileY.png'

Coordinate-Based Bubble Assumption

Incorrect:

Bubbles can always be positioned like markers by supplying
latitude and longitude on a basic tile layer.

Correct:

Use markers for direct coordinates.
Use bubbles for values associated with GeoJSON shapes.

Incorrect Color-Mapping Property

Incorrect:

colorMappings: []

Correct:

colorMapping: []

Incorrect Shape Property Path

Incorrect:

shapePropertyPath:
    'properties.name'

Correct:

shapePropertyPath:
    'name'

Annotation with Geographic Coordinates

Incorrect:

annotations: [
    {
        latitude:
            37.7749,
        longitude:
            -122.4194
    }
]

Use a marker for geographic coordinates.

Use x and y for an annotation:

annotations: [
    {
        content:
            '#annotation-template',
        x:
            '5%',
        y:
            '10%'
    }
]

Navigation Lines at the Maps Root

Incorrect:

map.navigationLineSettings =
    routes;

Correct:

map.layers[0]
    .navigationLineSettings =
        routes;

Undefined Geographic Data

Avoid:

shapeData:
    worldMap

unless worldMap has been imported, defined, or fetched successfully.

Unvalidated Event Names

Do not assume these events exist:

zoomEnd
panEnd
mouseMove
layerRender

Validate events and event types against the installed package.

Malformed CDN Markup

Incorrect:

https://cdn.syncfusion.com/...
    https://cdn.syncfusion.com/...
</a>

Correct:

<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js"></script>

Mixing Combined and Individual Bundles

Incorrect:

<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js"></script>
<script src="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/dist/global/ej2-base.min.js"></script>
<script src="https://cdn.syncfusion.com/ej2/34.2.2/ej2-maps/dist/global/ej2-maps.min.js"></script>

Correct:

<script src="https://cdn.syncfusion.com/ej2/34.2.2/dist/ej2.min.js"></script>

Encoded Executable HTML

Incorrect:

&lt;div id="maps-container"&gt;&lt;/div&gt;

Correct:

<div id="maps-container"></div>

Missing Cleanup

When the dynamic view is removed:

button.removeEventListener(
    'click',
    handleClick
);

controller.abort();

map.destroy();

Editor-Generated Markup

Remove the following from executable HTML, TypeScript, JavaScript, CSS, imports, commands, templates, and URLs:

<a>
<strong data-lexical-text="true">
<br>
data-lexical-text
Editor-generated class names
Encoded executable tags

FAQ

What does the syncfusion-javascript-maps skill do?

Guide to implementing Syncfusion Maps in TypeScript and JavaScript. Use this skill whenever the user needs to create interactive maps, add markers, visualize geographical data, work with map layers, apply color mapping, add annotations, configure legends, or handle map interactions and events. Works with TypeScript (module-based) and JavaScript (CDN/ES5).

How do I install syncfusion-javascript-maps?

Run npx skills add https://github.com/syncfusion/javascript-ui-controls-skills --skill syncfusion-javascript-maps in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/syncfusion-javascript-maps/ (personal) or .claude/skills/syncfusion-javascript-maps/ (project).

Which AI agents can use syncfusion-javascript-maps?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is syncfusion-javascript-maps safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains syncfusion-javascript-maps?

It is published by syncfusion in syncfusion/javascript-ui-controls-skills. It has 63 recorded installs.

More from syncfusion/javascript-ui-controls-skills

View all →

syncfusion-javascript-grid

syncfusion/javascript-ui-controls-skills

Open the skill to read its SKILL.md instructions.

syncfusion-javascript-common

syncfusion/javascript-ui-controls-skills

Open the skill to read its SKILL.md instructions.

syncfusion-javascript-dropdowns

syncfusion/javascript-ui-controls-skills

Comprehensive guide for implementing Syncfusion TypeScript dropdown components including AutoComplete, ComboBox, Mention, Dropdownlist, Multiselect, ListBox, and MultiColumn ComboBox. Use this when building selection interfaces, data binding, filtering, cascading dropdowns, dual list transfer, custom templates, and accessible dropdown experiences.

syncfusion-javascript-popups

syncfusion/javascript-ui-controls-skills

Open the skill to read its SKILL.md instructions.

syncfusion-javascript-license

syncfusion/javascript-ui-controls-skills

Open the skill to read its SKILL.md instructions.

syncfusion-javascript-tab

syncfusion/javascript-ui-controls-skills

Open the skill to read its SKILL.md instructions.

Popular code quality & workflow skills

View category →

grill-me

mattpocock/skills

A relentless interview to sharpen a plan or design.

Scan a codebase for deepening opportunities, present them as a visual HTML report, then grill through whichever one you pick.

handoff

mattpocock/skills

Compact the current conversation into a handoff document for another agent to pick up.

domain-modeling

mattpocock/skills

Build and sharpen a project's domain model. Use when discussing codebase terminology, writing or editing a GLOSSARY.md, or recording or editing an ADR.

codebase-design

mattpocock/skills

Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.

diagnosing-bugs

mattpocock/skills

Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.