Solid
Use the <instant-map> element in a Solid component. Solid has special prefixes for custom elements: attr: for attributes, prop: for properties and on: for events.
Install
Section titled “Install”npm install instantmap-jsAdd the map
Section titled “Add the map”Call defineInstantMap() once before rendering. A bare import "instantmap-js" is dropped by the bundler, so the element never gets defined.
import { defineInstantMap } from "instantmap-js";import { render } from "solid-js/web";import { App } from "./app";
defineInstantMap();render(() => <App />, document.getElementById("root")!);Tell TypeScript about the element.
import type { InstantMapElement, InstantMapEventMap, Marker } from "instantmap-js";import "solid-js";
declare module "solid-js" { namespace JSX { interface IntrinsicElements { "instant-map": JSX.HTMLAttributes<InstantMapElement> & { ref?: InstantMapElement | ((element: InstantMapElement) => void); "attr:center"?: string; "attr:zoom"?: number | string; "prop:markers"?: Marker[]; "on:markerclick"?: (event: InstantMapEventMap["markerclick"]) => void; }; } }}import { staticUrl } from "instantmap-js/server";import { listings } from "./listings";
const center: [number, number] = [-97.74, 30.27];const zoom = 12;const markers = listings();const poster = staticUrl({ center, zoom, width: 1200, height: 640, ratio: 2, markers });
export function App() { return ( <instant-map attr:center={center.join(",")} attr:zoom={zoom} prop:markers={markers} style={{ display: "block", position: "relative", height: "520px" }} > <img src={poster} alt="Map of Austin" width="1200" height="640" fetchpriority="high" style={{ position: "absolute", inset: "0", width: "100%", height: "100%", "object-fit": "cover" }} /> </instant-map> );}Render the first image on the server
Section titled “Render the first image on the server”A Vite and Solid app renders in the browser, so the server HTML has an empty root. The /static poster is the first map request once Solid renders, and the element swaps it for the live map. For a first image in the server HTML, render the same component with SolidStart.
Check what loads first:
npm run buildnpm run previewOpen the page with the network panel on. The /static? image is the first map request.
Markers, popups, events
Section titled “Markers, popups, events”Use on:markerclick and a ref for camera calls.
import { createSignal } from "solid-js";import type { InstantMapElement } from "instantmap-js";
export function App() { let map: InstantMapElement | undefined; const [opened, setOpened] = createSignal("Click a price to open its card.");
return ( <> <instant-map ref={map} on:markerclick={(event) => setOpened(`${event.detail.marker.title}, ${event.detail.marker.label}`)} attr:center={center.join(",")} attr:zoom={zoom} prop:markers={markers} /> <p>{opened()}</p> <button type="button" onClick={() => void map?.flyTo({ center: [-97.743, 30.267], zoom: 15 })}> Show downtown </button> </> );}Common mistakes
Section titled “Common mistakes”- Writing
center="..."ormarkers={...}without a prefix. Solid sets them as properties and the element ignores them. Useattr:for strings andprop:for the markers array. - Writing
onMarkerClick. Solid lowercases event names for custom elements. Useon:markerclick. - Importing
instantmap-jsfor its side effect only. CalldefineInstantMap(). - Giving the map no height. It collapses to nothing.
Prompt for your agent
Section titled “Prompt for your agent”Add an Instant Map to my SolidJS app. Follow https://instantmap.org/docs/frameworks/solid.md exactly. Call defineInstantMap() from instantmap before render, declare instant-map in the solid-js JSX IntrinsicElements, and use attr:center, attr:zoom, prop:markers and on:markerclick on the element. Render a staticUrl poster img from instantmap-js/server inside it and give the map a fixed height. Build and confirm the page loads a /static? image first.