Documentation

Getting Started

@geoql/v-mapkit is a set of Vue 3 components and composables for Apple MapKit JS — a declarative <VMap> container, annotation and overlay children, map controls, Look Around, and service composables for search, geocoding, directions, and points of interest.

Installation

Install the library and its peer dependency. vue@^3.5 is assumed to already be in your app; @vueuse/core powers the reactive lifecycle helpers.

pnpm
pnpm add @geoql/v-mapkit @vueuse/core
npm
npm install @geoql/v-mapkit @vueuse/core
yarn
yarn add @geoql/v-mapkit @vueuse/core

MapKit JS Token

Every map needs a MapKit JS token (a JWT) issued from Apple. Create a Maps identifier and a MapKit JS key in the Apple Developer Portal, then generate a token — either a long-lived developer token for local work or a short-lived token minted by your backend for production.

Warning

Never ship a long-lived developer token to the browser in production. Mint short-lived tokens server-side and pass them to <VMap> via access-token.

Basic Usage

Pass your token to access-token (the only required prop). Coordinates and regions are not props — MapKit owns the live map, so you set the initial region through the @map event once the instance is ready.

<script setup lang="ts">
  import { VMap, VMarkerAnnotation } from '@geoql/v-mapkit';
  import '@geoql/v-mapkit/style.css';

  const token = 'YOUR_MAPKIT_TOKEN';

  function onMap(map: mapkit.Map) {
    map.setRegionAnimated(
      new mapkit.CoordinateRegion(
        new mapkit.Coordinate(37.3349, -122.009),
        new mapkit.CoordinateSpan(0.06, 0.06),
      ),
    );
  }
</script>

<template>
  <VMap :access-token="token" color-scheme="light" @map="onMap">
    <VMarkerAnnotation
      :coordinates="[37.3349, -122.009]"
      :annotation="{ title: 'Apple Park' }"
    />
  </VMap>
</template>
Tip

<VMap> fills its parent — give the parent (or the map itself) an explicit height, e.g. class="h-[500px]" or style="height: 500px".

Global Registration

The default export is a Vue plugin that registers all 18 components globally, so you can skip per-file imports:

// main.ts
import { createApp } from 'vue';
import VMapKit from '@geoql/v-mapkit';
import '@geoql/v-mapkit/style.css';
import App from './App.vue';

createApp(App).use(VMapKit).mount('#app');

Nuxt Usage

MapKit JS is browser-only (it injects Apple's CDN script and uses WebGL), so wrap maps in <ClientOnly> and load the stylesheet globally.

// nuxt.config.ts
export default defineNuxtConfig({
  css: ['@geoql/v-mapkit/style.css'],
  vite: { optimizeDeps: { exclude: ['@geoql/v-mapkit'] } },
});
<script setup lang="ts">
  import { VMap, VMarkerAnnotation } from '@geoql/v-mapkit';
</script>

<template>
  <ClientOnly>
    <VMap :access-token="token" class="h-[500px]">
      <VMarkerAnnotation :coordinates="[37.3349, -122.009]" />
    </VMap>
    <template #fallback>
      <div class="h-[500px] animate-pulse rounded-lg bg-muted" />
    </template>
  </ClientOnly>
</template>

Next Steps