Maps
Interactive maps with MapLibre GL — open-source mapping for location features, markers, and geographic visualization.
Read this when adding maps to your app.
Useful for location pickers, store locators, or any geographic features.
Why MapLibre GL
MapLibre GL is an open-source fork of Mapbox GL. It provides beautiful vector maps without vendor lock-in or usage-based pricing. You can use free tile providers or host your own.
Catalyst uses react-map-gl as the React wrapper, which provides a declarative API for MapLibre. You get markers, popups, controls, and layers — all as React components.
Key Features
What you can build with maps:
Markers
Point locations. Place markers for stores, events, or any point of interest.
Controls
Navigation UI. Zoom, rotation, geolocation, and fullscreen controls.
Layers
Custom visualization. Heatmaps, clusters, and data-driven styling.
Catalyst Integration
Catalyst includes map examples and configuration:
app/(examples)/examples/maps/Map examples with markers and interactions
Quick Start
Basic map
"use client"
import Map from "react-map-gl/maplibre"
import "maplibre-gl/dist/maplibre-gl.css"
export function LocationMap() {
return (
<Map
initialViewState={{
longitude: -122.4,
latitude: 37.8,
zoom: 12,
}}
style={{ width: "100%", height: 400 }}
mapStyle="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"
/>
)
}Map with markers
import Map, { Marker, Popup } from "react-map-gl/maplibre"
import { useState } from "react"
const locations = [
{ id: 1, name: "Office", lng: -122.4, lat: 37.8 },
{ id: 2, name: "Warehouse", lng: -122.5, lat: 37.7 },
]
export function LocationsMap() {
const [selected, setSelected] = useState(null)
return (
<Map
initialViewState={{ longitude: -122.4, latitude: 37.8, zoom: 10 }}
style={{ width: "100%", height: 400 }}
mapStyle="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"
>
{locations.map((loc) => (
<Marker
key={loc.id}
longitude={loc.lng}
latitude={loc.lat}
onClick={() => setSelected(loc)}
/>
))}
{selected && (
<Popup
longitude={selected.lng}
latitude={selected.lat}
onClose={() => setSelected(null)}
>
{selected.name}
</Popup>
)}
</Map>
)
}Free Map Styles
These tile providers offer free tiers:
CartoDB Positron
Light, minimal style — great for data visualization
https://basemaps.cartocdn.com/gl/positron-gl-style/style.jsonCartoDB Dark Matter
Dark style — works well with dark mode
https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.jsonCartoDB Voyager
Colorful style — good for general purpose
https://basemaps.cartocdn.com/gl/voyager-gl-style/style.jsonFor production apps with high traffic, consider MapTiler or Stadia Maps for reliable tile hosting.
Tips
Import the CSS. MapLibre needs its stylesheet for controls and popups to render correctly.
Use "use client". Maps require browser APIs and must be client components.
Set explicit dimensions. The map container needs width and height — it won't grow to fill without them.
Handle loading state. Maps can take a moment to load tiles. Consider showing a loading indicator.
Learn More
For AI Agents
Key rules:
- Import from
react-map-gl/maplibre - Import
maplibre-gl/dist/maplibre-gl.css - Maps must be client components ("use client")
- Set explicit width and height on the Map
- Use free CartoDB styles for development
- See
/examples/mapsfor usage patterns