Skip to content

Next.js

View .md

Use instantmap-js/react in the App Router. The map works in a Server Component and sends its first image in the HTML.

Terminal window
npm install instantmap-js

Render InstantMap in a Server Component. Do not wrap it in dynamic(..., { ssr: false }).

app/page.tsx
import { InstantMap } from "instantmap-js/react";
import { listings } from "../lib/listings";
export default function Page() {
return (
<InstantMap
center={[-97.7431, 30.2672]}
zoom={11.5}
markers={listings}
alt="Map of stays in Austin"
style={{ height: 480, borderRadius: 12 }}
/>
);
}

Nothing to add. The server HTML contains an <img> whose src points at /static?. The browser paints it before any JavaScript loads, then the interactive map takes over.

Event handlers and refs need a Client Component. Mark the file "use client" and use the handle for camera calls.

app/listings-map.tsx
"use client";
import { useRef, useState } from "react";
import { InstantMap, type InstantMapHandle } from "instantmap-js/react";
import type { Marker } from "instantmap-js";
import type { Listing } from "../lib/listings";
export function ListingsMap({ listings }: { listings: Marker<Listing>[] }) {
const map = useRef<InstantMapHandle<Listing>>(null);
const [clicked, setClicked] = useState<Marker<Listing> | null>(null);
return (
<>
<button onClick={() => map.current?.fitBounds(listings, { padding: 48 })}>
Show all {listings.length} stays
</button>
<p>{clicked ? `Opened ${clicked.title}` : "Click a pin"}</p>
<InstantMap
ref={map}
center={[-97.7431, 30.2672]}
zoom={11.5}
markers={listings}
onMarkerClick={(marker) => setClicked(marker)}
alt="Map of stays in Austin"
style={{ height: 480, borderRadius: 12 }}
/>
</>
);
}

Pass listings from the Server Component as a prop. Each marker needs id, lng and lat. label, title, subtitle and href are optional.

  • Passing a function prop such as onMarkerClick from a Server Component. Move it into a file with "use client".
  • Using ref in a Server Component. Refs only work in Client Components.
  • Giving the map no height. Set style={{ height: 480 }} or a class that sets one.
Add an Instant Map to my Next.js App Router project. Follow https://instantmap.org/docs/frameworks/nextjs.md exactly. Render InstantMap from instantmap-js/react in a Server Component with a fixed height, and put onMarkerClick and refs in a separate "use client" file. Do not use next/dynamic with ssr: false. Run the build and confirm the server HTML contains an img with /static? in its src.

examples/nextjs on GitHub