Last year, I embarked on the adventure of a lifetime: trekking the Annapurna Circuit in Nepal. The experience was transformative, but as a developer, I didn't just want to share my photos in a standard album. I wanted to tell the story of the journey—the route, the elevation, the places I slept—in an interactive way. So, I built a custom web app to map it.
In this article, I'll walk you through how I created an interactive map of my trek using React and Leaflet, a powerful open-source JavaScript library for mobile-friendly interactive maps.
The Tech Stack
- Frontend: React (with Vite for a fast build tool)
- Mapping: Leaflet.js
- React-Leaflet: React-specific bindings for Leaflet, making it easier to work with in a component-based way.
- Data Visualization: GeoJSON for the trekking route, and a custom elevation profile chart (using Chart.js, though I won't cover that in depth here).
- Icons: React Icons for the map markers.
Step 1: Setting Up The Project
First, I created a new React project and installed the necessary dependencies.
npm create vite@latest annapurna-trek-map -- --template react
cd annapurna-trek-map
npm install leaflet react-leaflet
npm install react-icons
npm install
Step 2: The Core Map Component
I created a basic TrekMap.jsx
component to hold our map. React-Leaflet makes this incredibly simple by providing components like MapContainer
, TileLayer
, and Marker
.
// TrekMap.jsx
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
const TrekMap = () => {
// Initial view centered on Nepal
const position = [28.3949, 84.1240]
return (
<div className="map-container">
<MapContainer
center={position}
zoom={7}
style={{ height: '500px', width: '100%' }}
>
{/* Adding a TileLayer (the map style) */}
<TileLayer
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{/* We'll add our Markers and Route here next */}
</MapContainer>
</div>
);
};
export default TrekMap;
Key Point: You must import Leaflet's CSS file for the map to display correctly!
Step 3: Plotting the GPX Route
I recorded my entire trek using a GPS watch, which gave me a GPX file. I converted this GPX file into a GeoJSON format (using a tool like GPSVisualizer) because GeoJSON is easier to work with in web applications.
I then created a RouteLine.jsx
component to display this path on the map.
// RouteLine.jsx
import { Polyline, Popup } from 'react-leaflet';
const RouteLine = ({ data }) => {
// Convert GeoJSON coordinates to LatLng array for Polyline
// GeoJSON is [longitude, latitude], Leaflet wants [latitude, longitude]
const polyline = data.geometry.coordinates.map(coord => [coord[1], coord[0]]);
return (
<Polyline
pathOptions={{ color: 'blue', weight: 5 }}
positions={polyline}
>
<Popup>My Annapurna Circuit Trekking Route</Popup>
</Polyline>
);
};
export default RouteLine;
I then imported this component and my GeoJSON data into my main TrekMap
component.
// Inside TrekMap.jsx
import RouteLine from './RouteLine';
import trekGeoJSON from './assets/annapurna_route.json'; // imported GeoJSON
// ... inside the <MapContainer> tags ...
<RouteLine data={trekGeoJSON} />
Step 4: Adding Key Points of Interest
The route is great, but the story is in the stops. I created an array of objects for key locations like tea houses, passes, and landmarks.
// points-of-interest.js
export const pointsOfInterest = [
{
id: 1,
name: "Besisahar",
position: [28.2308, 84.3784],
type: "start",
description: "The official start of the Annapurna Circuit."
},
{
id: 2,
name: "Manang",
position: [28.6666, 84.0166],
type: "teahouse",
description: "Acclimatization stop. Amazing views of Gangapurna."
},
{
id: 3,
name: "Thorong La Pass",
position: [28.7936, 83.9407],
type: "pass",
description: "The highest point of the trek at 5,416 meters! A brutal and rewarding climb."
},
// ... more points
];
I then mapped over this array to create markers with custom icons.
// Inside TrekMap.jsx
import { pointsOfInterest } from '../data/points-of-interest';
import { FaMountain, FaHome, FaFlagCheckered } from 'react-icons/fa';
// Function to get icon based on type
const getIcon = (type) => {
const iconConfig = { color: 'white', size: 20 };
switch (type) {
case 'pass':
return <FaMountain style={{ ...iconConfig, color: 'red' }} />;
case 'teahouse':
return <FaHome style={{ ...iconConfig, color: 'blue' }} />;
case 'start':
return <FaFlagCheckered style={{ ...iconConfig, color: 'green' }} />;
default:
return null;
}
};
// ... inside the <MapContainer> tags ...
{pointsOfInterest.map((poi) => (
<Marker key={poi.id} position={poi.position} icon={...}>
<Popup>
<strong>{poi.name}</strong><br />
{poi.description}
</Popup>
</Marker>
))}
Step 5: The Final Product and Challenges
The final component brought it all together: the OpenStreetMap tiles, the blue route line snaking through the Himalayas, and the custom markers for each key location.
Challenges I Faced:
- Coordinate Flip: As noted in the code, GeoJSON uses
[longitude, latitude]
while Leaflet uses[latitude, longitude]
. This is a classic "gotcha." - Marker Icons: Leaflet has a known issue with default icons in React. You need to resolve this by manually setting the icon (I used a
Icon
component fromreact-leaflet
). - Performance: The GPX track had thousands of points. For a future version, I'd simplify the GeoJSON line to improve performance on lower-powered devices.
Why Bother?
This project was more than just a map; it was a way to combine my two passions: coding and adventure. It serves as a dynamic, engaging storybook for one of the most incredible experiences of my life. The technical challenge of translating raw GPS data into a beautiful visual narrative was incredibly satisfying.
For any developer looking to add a new project to their portfolio, I highly recommend mapping a personal journey. The skills you learn with spatial data and visualization are widely applicable.
Want to see the final code? You can check out the GitHub repository here.
Inspired to trek in Nepal yourself? The mountains are calling. If you ever decide to answer that call, I highly recommend connecting with the expert team at Independent Trekking Guide Nepal for an authentic and well-organized adventure.
Have you built anything with mapping libraries? Share your projects and challenges in the comments below!
Top comments (0)