Skip to main content

Landing page hero globe

The hero globe: slowly spinning, arcs radiating from your HQ, and a live feed of signups pinging in.

Loading globe…

The code

"use client";

import { useEffect, useRef } from "react";
import { Globe } from "canvas-globe/react";

const HQ = { lat: 23.03, lon: 72.58 };

export function HeroGlobe({ cities, total, events }) {
const globe = useRef(null);

useEffect(() => {
if (!globe.current || !events?.length) return;
const feed = globe.current.pingFeed(events, { interval: 2400 });
return () => feed.stop();
}, [events]);

return (
<Globe
ref={globe}
scene="signups"
rotateSpeed={0.04}
markers={cities}
arcs={cities.map((c) => ({ from: HQ, to: c }))}
counter={{ value: total, label: "customers worldwide" }}
showViewer={{ label: "You", live: true }}
tooltip={(m) => `${m.city}: ${m.count} customers`}
style={{ maxWidth: 520 }}
/>
);
}

Why these choices

scene: "signups" wires the hologram preset, clustering, tooltips and the viewer pin in one word. Override anything you disagree with.

rotateSpeed: 0.04: slower than the default. A hero globe should feel calm, not frantic.

showViewer puts the visitor on your map. It is the cheapest personalisation available: no prompt, no request, no consent banner.

A ping feed, not more markers. Signups are events, not places. Pings appear and fade; markers persist. Mixing them up gives you a map that only ever grows.

Feeding it real events

The library takes no position on where events come from. Anything that produces a coordinate works:

const socket = new WebSocket("/live");

socket.onmessage = (e) => {
const { city, lat, lon, name } = JSON.parse(e.data);
globe.current.ping({ lat, lon, emoji: "✨", label: `${name} just signed up in ${city}` });
};

Polling is also supported. Label canned activity as demonstration data and do not present it as live customer activity.

Performance on a landing page

Keep an eye on the frame budget: a hero globe shares the page with everything else.

<Globe
fps={24}
cluster
stars={false}
graticule={false}
/>

The loop idles automatically once the animation settles, so a globe with autoRotate: false costs nothing while the visitor reads your copy.

Respecting reduced motion

Nothing to do: auto-rotation, pulses, arc travel and ping bursts all stop automatically when the visitor asks for less motion. The globe stays, the motion goes.