diff --git a/agenda/trip.py b/agenda/trip.py
index 6bc4a7d..a306bee 100644
--- a/agenda/trip.py
+++ b/agenda/trip.py
@@ -143,38 +143,42 @@ def get_trip_routes(trip: Trip) -> list[StrDict]:
             if "from_airport" not in t or "to_airport" not in t:
                 continue
             fly_from, fly_to = t["from_airport"], t["to_airport"]
+            key = "_".join(["flight"] + sorted([fly_from["iata"], fly_to["iata"]]))
             routes.append(
                 {
                     "type": "flight",
+                    "key": key,
                     "from": latlon_tuple(fly_from),
                     "to": latlon_tuple(fly_to),
                 }
             )
-
-        else:
-            assert t["type"] == "train"
-            for leg in t["legs"]:
-                train_from, train_to = leg["from_station"], leg["to_station"]
-                geojson_filename = train_from.get("routes", {}).get(train_to["uic"])
-                if not geojson_filename:
-                    routes.append(
-                        {
-                            "type": "train",
-                            "from": latlon_tuple(train_from),
-                            "to": latlon_tuple(train_to),
-                        }
-                    )
-                    continue
-
-                if geojson_filename in seen_geojson:
-                    continue
-                seen_geojson.add(geojson_filename)
-
+            continue
+        assert t["type"] == "train"
+        for leg in t["legs"]:
+            train_from, train_to = leg["from_station"], leg["to_station"]
+            geojson_filename = train_from.get("routes", {}).get(train_to["uic"])
+            key = "_".join(["train"] + sorted([train_from["name"], train_to["name"]]))
+            if not geojson_filename:
                 routes.append(
                     {
                         "type": "train",
-                        "geojson": read_geojson(geojson_filename),
+                        "key": key,
+                        "from": latlon_tuple(train_from),
+                        "to": latlon_tuple(train_to),
                     }
                 )
+                continue
+
+            if geojson_filename in seen_geojson:
+                continue
+            seen_geojson.add(geojson_filename)
+
+            routes.append(
+                {
+                    "type": "train",
+                    "key": key,
+                    "geojson_filename": geojson_filename,
+                }
+            )
 
     return routes
diff --git a/templates/trips.html b/templates/trips.html
index 7da70cb..d0f5624 100644
--- a/templates/trips.html
+++ b/templates/trips.html
@@ -5,6 +5,11 @@
 {% set row = { "flight": flight_row, "train": train_row } %}
 
 {% block style %}
+
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
+     integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
+     crossorigin=""/>
+
 {% set conference_column_count = 6 %}
 {% set accommodation_column_count = 7 %}
 {% set travel_column_count = 7 %}
@@ -33,6 +38,13 @@
 .grid-item {
   /* Additional styling for grid items can go here */
 }
+
+#map {
+  height: 80vh;
+}
+
+
+
 </style>
 {% endblock %}
 
@@ -79,11 +91,69 @@
 {% block content %}
 <div class="p-2">
 
+  <div id="map"></div>
 
   <h1>Trips</h1>
     {{ section("Current", current, "attending") }}
     {{ section("Future", future, "going") }}
     {{ section("Past", past|reverse, "went") }}
 </div>
-
+{% endblock %}
+
+{% block scripts %}
+
+<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
+   integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
+   crossorigin=""></script>
+
+<script>
+var future_coordinates = {{ future_coordinates | tojson }};
+var future_routes = {{ future_routes | tojson }};
+
+// Initialize the map
+var map = L.map('map').fitBounds(future_coordinates.map(function(station) {
+  return [station.latitude, station.longitude];
+}));
+
+// Set up the tile layer
+L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+  attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
+}).addTo(map);
+
+var stationIcon = L.divIcon({
+  className: 'custom-div-icon',
+  html: "<div style='font-size: 24px;'>🚉</div>",
+  iconSize: [30, 42],
+});
+
+var airportIcon = L.divIcon({
+  className: 'custom-div-icon',
+  html: "<div style='font-size: 24px;'>✈️</div>",
+  iconSize: [30, 42],
+});
+
+// Add markers with appropriate icons to the map
+future_coordinates.forEach(function(item) {
+  var icon = item.type === "station" ? stationIcon : airportIcon;
+  var marker = L.marker([item.latitude, item.longitude], { icon: icon }).addTo(map);
+  marker.bindPopup(item.name);
+});
+
+// Draw routes
+future_routes.forEach(function(route) {
+  if (route.geojson) {
+    // If route is defined as GeoJSON
+    L.geoJSON(JSON.parse(route.geojson), {
+      style: function(feature) {
+        return {color: route.type === "train" ? "blue" : "blue"}; // Green for trains, blue for flights
+      }
+    }).addTo(map);
+  } else {
+    // If route is defined by 'from' and 'to' coordinates
+    var color = route.type === "train" ? "blue" : "red"; // Green for trains, red for flights
+    L.polyline([route.from, route.to], {color: color}).addTo(map);
+  }
+});
+
+</script>
 {% endblock %}
diff --git a/web_view.py b/web_view.py
index 9def860..1b57fb9 100755
--- a/web_view.py
+++ b/web_view.py
@@ -170,11 +170,35 @@ def trip_list() -> str:
     past = [item for item in trip_list if (item.end or item.start) < today]
     future = [item for item in trip_list if item.start > today]
 
+    future_coordinates = []
+    seen_future_coordinates: set[tuple[str, str]] = set()
+    future_routes = []
+    seen_future_routes: set[str] = set()
+    for trip in future:
+        for stop in agenda.trip.collect_trip_coordinates(trip):
+            key = (stop["type"], stop["name"])
+            if key in seen_future_coordinates:
+                continue
+            future_coordinates.append(stop)
+            seen_future_coordinates.add(key)
+
+        for route in agenda.trip.get_trip_routes(trip):
+            if route["key"] in seen_future_routes:
+                continue
+            future_routes.append(route)
+            seen_future_routes.add(route["key"])
+
+    for route in future_routes:
+        if "geojson_filename" in route:
+            route["geojson"] = agenda.trip.read_geojson(route.pop("geojson_filename"))
+
     return flask.render_template(
         "trips.html",
         current=current,
         past=past,
         future=future,
+        future_coordinates=future_coordinates,
+        future_routes=future_routes,
         today=today,
         get_country=agenda.get_country,
         format_list_with_ampersand=format_list_with_ampersand,
@@ -194,6 +218,9 @@ def trip_page(start: str) -> str:
 
     coordinates = agenda.trip.collect_trip_coordinates(trip)
     routes = agenda.trip.get_trip_routes(trip)
+    for route in routes:
+        if "geojson_filename" in route:
+            route["geojson"] = agenda.trip.read_geojson(route.pop("geojson_filename"))
 
     return flask.render_template(
         "trip_page.html",