Skip to content

Astro

View .md

You will end up with an Astro page that ships the first map image in the HTML and becomes an interactive map on the first hover, touch or scroll.

Terminal window
npm install instantmap-js

Put your markers in a module so the page and the script share them.

src/lib/listings.ts
import type { Marker } from "instantmap-js";
export const center: [number, number] = [-97.7431, 30.2672];
export const zoom = 12;
export const listings: Marker[] = [
{ id: 1, lng: -97.75, lat: 30.26, label: "$120", title: "Apartment 1", subtitle: "$120 per night" },
{ id: 2, lng: -97.73, lat: 30.28, label: "$85", title: "Apartment 2", subtitle: "$85 per night" },
];
---
import { staticUrl } from "instantmap-js/server";
import { center, listings, zoom } from "../lib/listings";
const poster = staticUrl({ center, zoom, width: 1280, height: 720, ratio: 2, markers: listings });
---
<instant-map
id="map"
center={center.join(",")}
zoom={zoom}
style="display:block;position:relative;height:520px"
>
<img
src={poster}
alt="Map of Austin"
width="1280"
height="720"
fetchpriority="high"
style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover"
/>
</instant-map>
<script>
import { defineInstantMap } from "instantmap-js";
import { listings } from "../lib/listings";
defineInstantMap();
const map = document.querySelector("instant-map");
if (map) map.markers = listings;
</script>

Astro bundles the <script> for you. It runs once in the browser.

staticUrl builds the URL of a server-rendered image. Astro puts that <img> in the HTML, so the map shows before any JavaScript loads.

If you would rather not build the markup, posterHtml returns the whole element:

---
import { posterHtml } from "instantmap-js/server";
const map = posterHtml({ center: [-97.7431, 30.2672], zoom: 12, width: 1280, height: 720, alt: "Map of Austin" });
---
<Fragment set:html={map} />
<script>
import { defineInstantMap } from "instantmap-js";
defineInstantMap();
</script>

To check it, view the page source or run curl:

Terminal window
curl -s http://localhost:4321/ | grep "<img"

You should see an <img src="https://.../static?..."> inside <instant-map>.

  • Use attributes for simple values: center, zoom, theme. Attributes are strings.
  • Use properties for objects. Set map.markers = listings in the script. Astro cannot pass an array through an attribute.
  • Listen with addEventListener:
map?.addEventListener("markerclick", (event) => {
const { marker } = (event as CustomEvent).detail;
console.log(marker.title);
});
  • Call methods on the element, for example map.fitBounds(listings, { padding: 40 }).

Markers set from the script do not change the server image. Pass the same markers to staticUrl so the first image matches.

  • Do not use client:only. Astro would skip the server render and you lose the instant first image. Use a plain <script>.
  • Import the element with defineInstantMap(). A bare import "instantmap-js" can be removed by the production build, and the element never registers.
  • Keep the element and the poster in agreement: same center, zoom and size.
  • Give the element a height. It has none by default, so the map is invisible without one.
  • Set position: relative on the element, so the poster can fill it.
Add Instant Map to my Astro site. Follow https://instantmap.org/docs/frameworks/astro.md
Show my listings as markers, render the first image on the server with staticUrl,
and register the element with defineInstantMap() in a page script.

A full working project is at examples/astro.