Markers

Markers are named pins on the map with optional colors, icons, labels, tooltips, and popups.

Basic Usage

{
  "markers": {
    "cafe": {
      "coordinates": [-73.98, 40.75],
      "color": "#e74c3c",
      "icon": "coffee",
      "tooltip": "Blue Bottle ยท Midtown",
      "popup": {
        "title": "Blue Bottle Coffee",
        "description": "Specialty coffee roaster"
      }
    },
    "park": {
      "coordinates": [-73.97, 40.76],
      "color": "#22c55e",
      "icon": "tree-pine",
      "tooltip": "Central Park ยท Manhattan"
    }
  }
}

Properties

PropertyTypeRequiredDescription
coordinates[lng, lat]YesMarker position
colorstringNoMarker color (hex)
iconstringNoBuilt-in icon name in kebab-case (see below)
labelstringNoText displayed below the marker
tooltipstringNoShort text shown on hover
popupstring | PopupSpecNoContent shown when marker is clicked
draggablebooleanNoWhether the marker can be dragged

Marker Styles

Markers come in two visual styles:

  • Dot โ€” default when no icon is set. A colored circle with a white border.
  • Icon โ€” when icon is set. A colored circle with a white icon inside.
{
  "markers": {
    "plain": { "coordinates": [0, 0], "color": "#e74c3c" },
    "with-icon": { "coordinates": [1, 0], "color": "#3498db", "icon": "star" }
  }
}

Built-in Icons

json-maps ships with 21 built-in icons (subset of Lucide as inline SVGs). No icon library dependency required.

IconNameGood for
๐Ÿ“map-pinGeneric location
โญstarHighlights, favorites
โค๏ธheartLiked places
๐ŸšฉflagStart/end points
โ˜•coffeeCafes
๐ŸดutensilsRestaurants
๐ŸจhotelHotels, lodging
๐Ÿขbuilding-2Offices, buildings
๐ŸŒฒtree-pineParks, nature
โ›ฐ๏ธmountainMountains, hiking
โœˆ๏ธplaneAirports
๐Ÿš‚trainTrain stations
๐Ÿš—carParking, driving
๐ŸšŒbusBus stops
๐Ÿš›truckLogistics, delivery
๐ŸšขshipPorts, harbors
โ›ชchurchReligious sites
๐Ÿ›’shopping-cartShopping
๐Ÿ“ทcameraPhoto spots, landmarks
๐Ÿ›๏ธlandmarkMonuments, government
โ›บtentCamping

Custom Icons

Need icons beyond the built-in set? Override the Marker component with your own that uses any icon library. See Component Slots.

import { MapRenderer } from "json-maps";
import { DynamicIcon } from "lucide-react/dynamic"; // or any icon lib

function CustomMarker({ marker, color }) {
  return (
    <div style={{ background: color, borderRadius: "50%", padding: 6 }}>
      <DynamicIcon name={marker.icon} size={16} color="white" />
    </div>
  );
}

<MapRenderer spec={spec} components={{ Marker: CustomMarker }} />

Tooltip vs Popup

  • Tooltip โ€” appears on hover, disappears on mouse leave. Short, one-line text.
  • Popup โ€” appears on click. Can contain title, description, and image.

The popup field accepts either a simple string or a rich object:

Simple string:

{ "popup": "A brief description" }

Rich popup with title, description, and image:

{
  "popup": {
    "title": "Eiffel Tower",
    "description": "330m iron lattice tower on the Champ de Mars",
    "image": "https://example.com/eiffel.jpg"
  }
}

Events

Marker events are handled via props on MapRenderer. See Events for details.

<MapRenderer
  spec={spec}
  onMarkerClick={(id, coords) => console.log(id, coords)}
  onMarkerDragEnd={(id, coords) => console.log(id, coords)}
/>

Custom Markers

You can replace the default marker component with your own. See Component Slots.

Why Named Map?

Markers use a named map ({ "cafe": {...} }) instead of an array. This makes it easy to:

  • Reference individual markers by key
  • Update or remove a specific marker via JSON patches
  • Stream marker additions without replacing the whole array