Skip to content
Docs version
@hungpvq/vue-map@1.1.0@hungpvq/vue-map-core@1.1.0@hungpvq/vue-map-dataset@1.1.0@hungpvq/vue-map-draw@1.1.0@hungpvq/map-draw@1.1.0@hungpvq/react-map@1.1.0@hungpvq/react-map-core@1.1.0@hungpvq/react-map-dataset@1.1.0@hungpvq/react-map-draw@1.1.0

Install from npm (external apps)

Guide for apps outside this monorepo that install @hungpvq/* from the npm registry (greenfield).

Related: Getting started · Minimal starter · Peers and bundle · Stable API

What to install

Recommended — meta package (pulls map-core, map-dataset, framework adapters, draggable, shared):

bash
# Vue
npm install @hungpvq/vue-map maplibre-gl vue

# React
npm install @hungpvq/react-map maplibre-gl react react-dom

maplibre-gl and the framework stay peers (single instance in the app). Do not rely on a second copy nested under @hungpvq/*.

Version family

Map packages release together under tag map@{version} (fixed group). Prefer aligning @hungpvq/map-* / vue-map-* / react-map-* on the same minor. Meta packages declare ^ ranges on the stack; pin or lockfile if you need stricter control.

Meta vs domain imports

From meta (@hungpvq/vue-map / react-map)Still import from domain packages
installMapApp (+ Vue createMapAppPlugin)UI: Map, controls → vue-map-core / react-map-core
./style.css (all shell CSS)Dataset UI: LayerControl, hooks → vue-map-dataset / react-map-dataset
Transitive deps (core, dataset, draggable, shared, icons)Builders / types: @hungpvq/map-core, @hungpvq/map-dataset (and subpaths)

Meta is an install + bootstrap bag, not a barrel of every component.

Bootstrap (once per app)

ts
// Vue
import { createApp } from 'vue';
import { installMapApp } from '@hungpvq/vue-map';
import '@hungpvq/vue-map/style.css';

const app = createApp(App);
installMapApp(app);
app.mount('#app');
ts
// React — call once at app entry (before first map mount)
import { installMapApp } from '@hungpvq/react-map';
import '@hungpvq/react-map/style.css';

installMapApp();

Without installMapApp, layer menus / style / export / attribute table UI do not register.

Minimal map (copy-paste)

Same UI as Minimal starter, with meta CSS + bootstrap.

Vue

vue
<script setup lang="ts">
import type { MapSimple } from '@hungpvq/map-core';
import { Map } from '@hungpvq/vue-map-core';
import { LayerControl, useMapDataset } from '@hungpvq/vue-map-dataset';
import { createGeoJsonDataset } from '@hungpvq/map-dataset/geojson';
import type { FeatureCollection } from 'geojson';

const sample: FeatureCollection = {
  type: 'FeatureCollection',
  features: [
    {
      type: 'Feature',
      properties: { name: 'A' },
      geometry: { type: 'Point', coordinates: [106.7, 10.8] },
    },
  ],
};

function onMapLoaded(map: MapSimple) {
  const { addDataset } = useMapDataset(map.id);
  addDataset(
    createGeoJsonDataset({
      name: 'Sample points',
      geojson: sample,
      type: 'point',
      color: '#e74c3c',
    }),
  );
}
</script>

<template>
  <Map @map-loaded="onMapLoaded">
    <LayerControl position="top-left" show />
  </Map>
</template>

Entry:

ts
import { createApp } from 'vue';
import { installMapApp } from '@hungpvq/vue-map';
import '@hungpvq/vue-map/style.css';
import App from './App.vue';

const app = createApp(App);
installMapApp(app);
app.mount('#app');

React

tsx
import type { MapSimple } from '@hungpvq/map-core';
import { Map } from '@hungpvq/react-map-core';
import { LayerControl, useMapDataset } from '@hungpvq/react-map-dataset';
import { createGeoJsonDataset } from '@hungpvq/map-dataset/geojson';
import type { FeatureCollection } from 'geojson';

const sample: FeatureCollection = {
  type: 'FeatureCollection',
  features: [
    {
      type: 'Feature',
      properties: { name: 'A' },
      geometry: { type: 'Point', coordinates: [106.7, 10.8] },
    },
  ],
};

export function MinimalMap() {
  const { addDataset, setMapId } = useMapDataset();

  function onMapLoaded(map: MapSimple) {
    setMapId(map.id);
    void addDataset(
      createGeoJsonDataset({
        name: 'Sample points',
        geojson: sample,
        type: 'point',
        color: '#e74c3c',
      }),
    );
  }

  return (
    <Map onMapLoaded={onMapLoaded}>
      <LayerControl position="top-left" show />
    </Map>
  );
}

Entry (once):

ts
import { installMapApp } from '@hungpvq/react-map';
import '@hungpvq/react-map/style.css';

installMapApp();

Optional installs (feature peers)

Install only when you use the feature:

FeaturePackages
Print / exportFilefile-saver
Legend expression eval@maplibre/maplibre-gl-style-spec
CreateControl file formatsshpjs, papaparse, @tmcw/togeojson, @xmldom/xmldom, jszip, topojson-client, … — Peers and bundle
Off-main-thread GIS parseVite plugin @hungpvq/map-dataset/viteWorker
Draw / edit@hungpvq/vue-map-draw or react-map-draw + @hungpvq/map-drawDraw
Devtools panel@hungpvq/vue-map-devtools or react-map-devtoolsDevtools

Defaults (single-app / single theme)

Out of the box:

  • Theme: scope: 'document' (html + prefers-color-scheme when auto)
  • Stores / platform accessors: process-wide (globalThis)

For independent multi-map chrome themes use ThemeControl / applyMapTheme with scope: 'map'Map store.

Troubleshooting (external)

SymptomCheck
Unstyled UIImport @hungpvq/vue-map/style.css (or react-map) once; or the full a-la-carte CSS set
Empty layer menus / no style editorCall installMapApp before mounting maps
Two MapLibre instances / broken GLOnly one maplibre-gl in the app (peer); avoid bundling a second copy
Peer warnings for turf / proj4Expected to come with @hungpvq/map-core — do not install @turf/turf for the library
CreateControl missing formatInstall the optional GIS peer for that format
Types / exports missingImport Stable symbols from documented packages — Stable API

Next