How to Add Interactive Maps to Your Personal Website
Static lists of places you've been can be dull. Interactive maps, on the other hand, offer a dynamic and visually engaging way to tell your story. On my personal website, I've included two distinct maps: a world map to showcase the countries I've visited, and a detailed map of Hong Kong highlighting my favorite local spots.
This guide will walk you through the technical implementation of both maps, providing a step-by-step tutorial for you to integrate similar features into your own projects.
Part 1: The World Map with react-simple-maps
For a clean, stylized, and lightweight world map, react-simple-maps is an excellent choice. It's a React library that makes it easy to create projections, add interactivity, and customize your map's appearance.
The implementation for this map can be found in src/components/world-map.tsx
.
Step 1: Get Your Map Data and Set Up the Component
First, you'll need geographic data for the world's countries, typically in TopoJSON or GeoJSON format. You can find files like world-countries.json
online. Once you have your data, you can set up the main map component.
The ComposableMap
component acts as a container for your map. Inside, the Geographies
component fetches and parses your JSON data.
// src/components/world-map.tsx
import { ComposableMap, Geographies, Geography } from "react-simple-maps";
import geoData from "../../public/world-countries.json"; // Your map data
const WorldMap = () => (
<ComposableMap
projection="geoMercator"
projectionConfig={% raw %}{{
scale: 150, // Adjust the scale to zoom in/out
}}{% endraw %}
>
<Geographies geography={geoData}>
{({ geographies }) =>
geographies.map((geo) => (
<Geography key={geo.rsmKey} geography={geo} />
))
}
</Geographies>
</ComposableMap>
);
Step 2: Highlight Visited Countries
To make the map your own, you can highlight the countries you've visited. Create an array of the countries' ISO 3166-1 alpha-3 codes and use it to conditionally style each Geography
component.
// src/components/world-map.tsx
const visitedCountries = [
"USA", "CHN", "JPN", "FRA", // and so on...
];
// Inside the component...
const isVisited = visitedCountries.includes(geo.id);
return (
<Geography
key={geo.rsmKey}
geography={geo}
style={% raw %}{{
default: {
fill: isVisited ? "#5AC8FA" : "#E5E7EB", // Visited color vs. default
outline: "none",
},
hover: {
fill: "#007AFF", // Hover color
outline: "none",
},
}}{% endraw %}
/>
);
This code checks if a country's ID (its ISO code) is present in the visitedCountries
array and applies a different fill color if it is.
Step 3: Add Interactivity with Tooltips
A simple tooltip that shows the country's name on hover adds a great layer of interactivity. This can be managed with a React state hook.
// src/components/world-map.tsx
const [hoveredCountry, setHoveredCountry] = useState<string | null>(null);
//...
<Geography
//...
onMouseEnter={() => setHoveredCountry(geo.properties.name)}
onMouseLeave={() => setHoveredCountry(null)}
/>
//... and render the tooltip conditionally
{hoveredCountry && (
<div className="absolute top-2 left-1/2 transform -translate-x-1/2 bg-white p-2 rounded shadow">
{hoveredCountry}
</div>
)}
The onMouseEnter
and onMouseLeave
events update the state, which in turn shows or hides the tooltip.
Part 2: A Detailed Local Map with react-leaflet
When you need a more detailed, zoomable map with custom markers, react-leaflet is the perfect tool. It provides a React wrapper around the popular Leaflet.js library.
The implementation for this map is in src/components/hong-kong-map.tsx
.
Step 1: Set Up the Leaflet Map Container
The MapContainer
component from react-leaflet creates the map. You'll also need a TileLayer
, which fetches map tiles from a service like OpenStreetMap.
// src/components/hong-kong-map.tsx
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css"; // Don't forget to import the CSS
const HongKongMap = () => (
<MapContainer center={[22.35, 114.15]} zoom={10} style={% raw %}{{ height: '400px', width: '100%' }}{% endraw %}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
{/* Markers will be rendered here */}
</MapContainer>
);
Step 2: Define Custom Markers and Locations
To highlight specific spots, you'll need their coordinates. You can store this data in an object. For a more personalized touch, you can create custom icons for your markers.
// src/components/hong-kong-map.tsx
import L from "leaflet";
// Define custom icons
const natureIcon = new L.Icon({
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
});
// Define your locations
const locations = {
"Tai Mo Shan": {
name: "Tai Mo Shan (大帽山)",
coordinates: [22.4197, 114.1175],
type: "nature"
},
// ... more locations
};
Step 3: Render Markers and Popups
Finally, map over your locations data to render a Marker
for each spot. Use the icon
prop to apply your custom icons and add a Popup
to display more information when a marker is clicked.
// Inside the MapContainer
{Object.entries(locations).map(([key, location]) => (
<Marker
key={key}
position={location.coordinates as [number, number]}
icon={location.type === 'nature' ? natureIcon : urbanIcon}
>
<Popup>
<span className="font-semibold">{location.name}</span>
<br />
{location.description}
</Popup>
</Marker>
))}
This will place a marker for each location on the map, complete with a custom icon and a popup that reveals more details on click.
Conclusion
By following these steps, you can create beautiful and informative maps that add a personal and professional touch to your website. The combination of react-simple-maps for global visualization and react-leaflet for detailed local exploration provides a comprehensive mapping solution that can showcase your travels and experiences in an engaging way.
The key benefits of this approach include:
- Visual storytelling: Maps provide an immediate visual impact that text alone cannot achieve
- Interactive engagement: Users can explore your experiences through hover effects and clickable markers
- Responsive design: Both libraries work well across different screen sizes
- Customization: You can tailor colors, icons, and interactions to match your website's design
- Performance: Lightweight libraries ensure fast loading times
Whether you're showcasing your global travels or highlighting local favorites, interactive maps can transform your personal website into a more engaging and memorable experience for your visitors.