diff --git a/config/config.exs b/config/config.exs
index 5874de5af..23f3cb4ee 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -210,6 +210,9 @@ config :mobilizon, :maps,
   tiles: [
     endpoint: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
     attribution: "© The OpenStreetMap Contributors"
+  ],
+  routing: [
+    type: :openstreetmap
   ]
 
 config :mobilizon, :anonymous,
diff --git a/js/schema.graphql b/js/schema.graphql
index c9e3930dd..86f757e80 100644
--- a/js/schema.graphql
+++ b/js/schema.graphql
@@ -238,6 +238,12 @@ type Tag {
   related: [Tag]
 }
 
+"Instance map routing configuration"
+type Routing {
+  "The instance's routing type"
+  type: RoutingType
+}
+
 "Language information"
 type Language {
   "The iso-639-3 language code"
@@ -420,6 +426,9 @@ type Events {
 type Maps {
   "The instance's maps tiles configuration"
   tiles: Tiles
+
+  "The instance's maps routing configuration"
+  routing: Routing
 }
 
 "Search groups result"
@@ -659,6 +668,14 @@ interface Interactable {
   url: String
 }
 
+enum RoutingType {
+  "Redirect to openstreetmap.org's direction endpoint"
+  OPENSTREETMAP
+
+  "Redirect to Google Maps's direction endpoint"
+  GOOGLE_MAPS
+}
+
 "A struct containing the id of the deleted object"
 type DeletedObject {
   id: ID
@@ -2856,7 +2873,7 @@ type PaginatedGroupList {
   total: Int
 }
 
-"Instance tiles configuration"
+"Instance map tiles configuration"
 type Tiles {
   "The instance's tiles endpoint"
   endpoint: String
diff --git a/js/src/graphql/config.ts b/js/src/graphql/config.ts
index 33d3e40e2..3dd903581 100644
--- a/js/src/graphql/config.ts
+++ b/js/src/graphql/config.ts
@@ -51,6 +51,9 @@ export const CONFIG = gql`
           endpoint
           attribution
         }
+        routing {
+          type
+        }
       }
       geocoding {
         provider
diff --git a/js/src/i18n/en_US.json b/js/src/i18n/en_US.json
index c4a686b25..24f6c7b79 100644
--- a/js/src/i18n/en_US.json
+++ b/js/src/i18n/en_US.json
@@ -813,12 +813,15 @@
   "View all events": "View all events",
   "You will find here all the events you have created or of which you are a participant.": "You will find here all the events you have created or of which you are a participant.",
   "Create event": "Create event",
-  "You didn't create or join any event yet": "You didn't create or join any event yet",
+  "You didn't create or join any event yet.": "You didn't create or join any event yet.",
   "create an event": "create an event",
   "explore the events": "explore the events",
   "Do you wish to {create_event} or {explore_events}?": "Do you wish to {create_event} or {explore_events}?",
-  "You are not part of any group": "You are not part of any group",
+  "You are not part of any group.": "You are not part of any group.",
   "create a group": "create a group",
   "explore the groups": "explore the groups",
-  "Do you wish to {create_group} or {explore_groups}?": "Do you wish to {create_group} or {explore_groups}?"
+  "Do you wish to {create_group} or {explore_groups}?": "Do you wish to {create_group} or {explore_groups}?",
+  "Type or select a date…": "Type or select a date…",
+  "Getting there": "Getting there",
+  "Groups are not enabled on this instance.": "Groups are not enabled on this instance."
 }
diff --git a/js/src/i18n/fr_FR.json b/js/src/i18n/fr_FR.json
index 8d4b9a144..f3a5e6570 100644
--- a/js/src/i18n/fr_FR.json
+++ b/js/src/i18n/fr_FR.json
@@ -914,5 +914,8 @@
   "You are not part of any group.": "Vous ne faites partie d'aucun groupe.",
   "create a group": "créer un groupe",
   "explore the groups": "explorer les groupes",
-  "Do you wish to {create_group} or {explore_groups}?": "Voulez-vous {create_group} ou {explore_groups} ?"
+  "Do you wish to {create_group} or {explore_groups}?": "Voulez-vous {create_group} ou {explore_groups} ?",
+  "Type or select a date…": "Entrez ou sélectionnez une date…",
+  "Getting there": "S'y rendre",
+  "Groups are not enabled on this instance.": "Les groupes ne sont pas activés sur cette instance."
 }
diff --git a/js/src/types/address.model.ts b/js/src/types/address.model.ts
index 6bc2f7052..7ba83b53d 100644
--- a/js/src/types/address.model.ts
+++ b/js/src/types/address.model.ts
@@ -15,6 +15,12 @@ export interface IAddress {
   originId?: string;
 }
 
+export interface IPoiInfo {
+  name: string;
+  alternativeName: string;
+  poiIcon: IPOIIcon;
+}
+
 export class Address implements IAddress {
   country = "";
 
@@ -54,7 +60,7 @@ export class Address implements IAddress {
     this.originId = hash.originId;
   }
 
-  get poiInfos(): { name: string; alternativeName: string; poiIcon: IPOIIcon } {
+  get poiInfos(): IPoiInfo {
     /* generate name corresponding to poi type */
     let name = "";
     let alternativeName = "";
diff --git a/js/src/types/config.model.ts b/js/src/types/config.model.ts
index af43f666e..6d391d0a8 100644
--- a/js/src/types/config.model.ts
+++ b/js/src/types/config.model.ts
@@ -1,4 +1,4 @@
-import { InstancePrivacyType, InstanceTermsType } from "./enums";
+import { InstancePrivacyType, InstanceTermsType, RoutingType } from "./enums";
 import type { IProvider } from "./resource";
 
 export interface IOAuthProvider {
@@ -58,6 +58,9 @@ export interface IConfig {
       endpoint: string;
       attribution: string | null;
     };
+    routing: {
+      type: RoutingType;
+    };
   };
   geocoding: {
     provider: string;
diff --git a/js/src/types/enums.ts b/js/src/types/enums.ts
index 9eeeb5af9..a081a3463 100644
--- a/js/src/types/enums.ts
+++ b/js/src/types/enums.ts
@@ -160,3 +160,15 @@ export enum Openness {
   MODERATED = "MODERATED",
   OPEN = "OPEN",
 }
+
+export enum RoutingType {
+  OPENSTREETMAP = "OPENSTREETMAP",
+  GOOGLE_MAPS = "GOOGLE_MAPS",
+}
+
+export enum RoutingTransportationType {
+  FOOT = "FOOT",
+  BIKE = "BIKE",
+  TRANSIT = "TRANSIT",
+  CAR = "CAR",
+}
diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue
old mode 100644
new mode 100755
index 5c665e347..290dee24f
--- a/js/src/views/Event/Event.vue
+++ b/js/src/views/Event/Event.vue
@@ -84,9 +84,9 @@
                   <tag>{{ tag.title }}</tag>
                 </router-link>
               </p>
-              <b-tag type="is-warning" size="is-medium" v-if="event.draft">{{
-                $t("Draft")
-              }}</b-tag>
+              <b-tag type="is-warning" size="is-medium" v-if="event.draft"
+                >{{ $t("Draft") }}
+              </b-tag>
               <span
                 class="event-status"
                 v-if="event.status !== EventStatus.CONFIRMED"
@@ -325,7 +325,7 @@
                     <span
                       class="map-show-button"
                       @click="showMap = !showMap"
-                      v-if="physicalAddress && physicalAddress.geom"
+                      v-if="physicalAddress.geom"
                       >{{ $t("Show map") }}</span
                     >
                   </div>
@@ -526,8 +526,8 @@
                     class="button"
                     ref="cancelButton"
                     @click="isJoinConfirmationModalActive = false"
-                    >{{ $t("Cancel") }}</b-button
-                  >
+                    >{{ $t("Cancel") }}
+                  </b-button>
                   <b-button type="is-primary" native-type="submit">
                     {{ $t("Confirm my participation") }}
                   </b-button>
@@ -537,17 +537,77 @@
           </div>
         </b-modal>
         <b-modal
+          class="map-modal"
           v-if="physicalAddress && physicalAddress.geom"
           :active.sync="showMap"
+          has-modal-card
+          full-screen
         >
-          <div class="map">
-            <map-leaflet
-              :coords="physicalAddress.geom"
-              :marker="{
-                text: physicalAddress.fullName,
-                icon: physicalAddress.poiInfos.poiIcon.icon,
-              }"
-            />
+          <div class="modal-card">
+            <header class="modal-card-head">
+              <button type="button" class="delete" @click="showMap = false" />
+            </header>
+            <div class="modal-card-body">
+              <section class="map">
+                <map-leaflet
+                  :coords="physicalAddress.geom"
+                  :marker="{
+                    text: physicalAddress.fullName,
+                    icon: physicalAddress.poiInfos.poiIcon.icon,
+                  }"
+                />
+              </section>
+              <section class="columns is-centered map-footer">
+                <div class="column is-half has-text-centered">
+                  <p class="address">
+                    <i class="mdi mdi-map-marker"></i>
+                    {{ physicalAddress.fullName }}
+                  </p>
+                  <p class="getting-there">{{ $t("Getting there") }}</p>
+                  <div
+                    class="buttons"
+                    v-if="
+                      addressLinkToRouteByCar ||
+                      addressLinkToRouteByBike ||
+                      addressLinkToRouteByFeet
+                    "
+                  >
+                    <a
+                      class="button"
+                      target="_blank"
+                      v-if="addressLinkToRouteByFeet"
+                      :href="addressLinkToRouteByFeet"
+                    >
+                      <i class="mdi mdi-walk"></i
+                    ></a>
+                    <a
+                      class="button"
+                      target="_blank"
+                      v-if="addressLinkToRouteByBike"
+                      :href="addressLinkToRouteByBike"
+                    >
+                      <i class="mdi mdi-bike"></i
+                    ></a>
+                    <a
+                      class="button"
+                      target="_blank"
+                      v-if="addressLinkToRouteByTransit"
+                      :href="addressLinkToRouteByTransit"
+                    >
+                      <i class="mdi mdi-bus"></i
+                    ></a>
+                    <a
+                      class="button"
+                      target="_blank"
+                      v-if="addressLinkToRouteByCar"
+                      :href="addressLinkToRouteByCar"
+                    >
+                      <i class="mdi mdi-car"></i>
+                    </a>
+                  </div>
+                </div>
+              </section>
+            </div>
           </div>
         </b-modal>
       </div>
@@ -563,6 +623,8 @@ import {
   EventStatus,
   EventVisibility,
   ParticipantRole,
+  RoutingTransportationType,
+  RoutingType,
 } from "@/types/enums";
 import {
   EVENT_PERSON_PARTICIPATION,
@@ -602,6 +664,7 @@ import ActorCard from "../../components/Account/ActorCard.vue";
 import PopoverActorCard from "../../components/Account/PopoverActorCard.vue";
 import { IParticipant } from "../../types/participant.model";
 
+// noinspection TypeScriptValidateTypes
 @Component({
   components: {
     EventMetadataBlock,
@@ -734,6 +797,65 @@ export default class Event extends EventMixin {
 
   messageForConfirmation = "";
 
+  RoutingParamType = {
+    [RoutingType.OPENSTREETMAP]: {
+      [RoutingTransportationType.FOOT]: "engine=fossgis_osrm_foot",
+      [RoutingTransportationType.BIKE]: "engine=fossgis_osrm_bike",
+      [RoutingTransportationType.TRANSIT]: null,
+      [RoutingTransportationType.CAR]: "engine=fossgis_osrm_car",
+    },
+    [RoutingType.GOOGLE_MAPS]: {
+      [RoutingTransportationType.FOOT]: "dirflg=w",
+      [RoutingTransportationType.BIKE]: "dirflg=b",
+      [RoutingTransportationType.TRANSIT]: "dirflg=r",
+      [RoutingTransportationType.CAR]: "driving",
+    },
+  };
+
+  makeNavigationPath(
+    transportationType: RoutingTransportationType
+  ): string | undefined {
+    const geometry = this.physicalAddress?.geom;
+    if (geometry) {
+      const routingType = this.config.maps.routing.type;
+      /**
+       * build urls to routing map
+       */
+      if (!this.RoutingParamType[routingType][transportationType]) {
+        return;
+      }
+
+      const urlGeometry = geometry.split(";").reverse().join(",");
+
+      switch (routingType) {
+        case RoutingType.GOOGLE_MAPS:
+          return `https://maps.google.com/?saddr=Current+Location&daddr=${urlGeometry}&${this.RoutingParamType[routingType][transportationType]}`;
+        case RoutingType.OPENSTREETMAP:
+        default: {
+          const bboxX = geometry.split(";").reverse()[0];
+          const bboxY = geometry.split(";").reverse()[1];
+          return `https://www.openstreetmap.org/directions?from=&to=${urlGeometry}&${this.RoutingParamType[routingType][transportationType]}#map=14/${bboxX}/${bboxY}`;
+        }
+      }
+    }
+  }
+
+  get addressLinkToRouteByCar(): undefined | string {
+    return this.makeNavigationPath(RoutingTransportationType.CAR);
+  }
+
+  get addressLinkToRouteByBike(): undefined | string {
+    return this.makeNavigationPath(RoutingTransportationType.BIKE);
+  }
+
+  get addressLinkToRouteByFeet(): undefined | string {
+    return this.makeNavigationPath(RoutingTransportationType.FOOT);
+  }
+
+  get addressLinkToRouteByTransit(): undefined | string {
+    return this.makeNavigationPath(RoutingTransportationType.TRANSIT);
+  }
+
   get eventTitle(): undefined | string {
     if (!this.event) return undefined;
     return this.event.title;
@@ -1096,6 +1218,7 @@ export default class Event extends EventMixin {
 
   get physicalAddress(): Address | null {
     if (!this.event.physicalAddress) return null;
+
     return new Address(this.event.physicalAddress);
   }
 
@@ -1225,6 +1348,7 @@ div.sidebar {
     a {
       text-decoration: none;
     }
+
     span {
       &.tag {
         margin: 0 2px;
@@ -1389,9 +1513,31 @@ a.participations-link {
   font-size: 1rem;
 }
 
-div.map {
-  height: 900px;
-  width: 100%;
-  padding: 25px 5px 0;
+.map-modal {
+  .modal-card-head {
+    justify-content: flex-end;
+    button.delete {
+      margin-right: 1rem;
+    }
+  }
+
+  section.map {
+    height: calc(100% - 8rem);
+    width: calc(100% - 20px);
+  }
+
+  section.map-footer {
+    p.address {
+      margin: 1rem auto;
+    }
+    div.buttons {
+      justify-content: center;
+    }
+  }
+}
+
+.no-border {
+  border: 0;
+  cursor: auto;
 }
 </style>
diff --git a/js/src/views/Search.vue b/js/src/views/Search.vue
index e02794676..765c96899 100644
--- a/js/src/views/Search.vue
+++ b/js/src/views/Search.vue
@@ -127,7 +127,7 @@
           </span>
         </template>
         <b-message v-if="config && !config.features.groups" type="is-danger">
-          {{ $t("Groups are not enabled on your server.") }}
+          {{ $t("Groups are not enabled on this instance.") }}
         </b-message>
         <div v-else-if="searchGroups.total > 0">
           <div class="columns is-multiline">
diff --git a/js/tests/unit/specs/mocks/config.ts b/js/tests/unit/specs/mocks/config.ts
index 84c4f80b1..271d71ce3 100644
--- a/js/tests/unit/specs/mocks/config.ts
+++ b/js/tests/unit/specs/mocks/config.ts
@@ -56,6 +56,9 @@ export const configMock = {
           attribution: "© The OpenStreetMap Contributors",
           endpoint: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
         },
+        routing: {
+          type: "OPENSTREETMAP",
+        },
       },
       name: "Mobilizon",
       registrationsAllowlist: false,
diff --git a/lib/graphql/resolvers/config.ex b/lib/graphql/resolvers/config.ex
index 181caa0e4..a1b8c3e8c 100644
--- a/lib/graphql/resolvers/config.ex
+++ b/lib/graphql/resolvers/config.ex
@@ -117,6 +117,9 @@ defmodule Mobilizon.GraphQL.Resolvers.Config do
         tiles: %{
           endpoint: Config.instance_maps_tiles_endpoint(),
           attribution: Config.instance_maps_tiles_attribution()
+        },
+        routing: %{
+          type: Config.instance_maps_routing_type()
         }
       },
       resource_providers: Config.instance_resource_providers(),
diff --git a/lib/graphql/schema/config.ex b/lib/graphql/schema/config.ex
index c48058446..a2d9d02ab 100644
--- a/lib/graphql/schema/config.ex
+++ b/lib/graphql/schema/config.ex
@@ -106,16 +106,29 @@ defmodule Mobilizon.GraphQL.Schema.ConfigType do
   """
   object :maps do
     field(:tiles, :tiles, description: "The instance's maps tiles configuration")
+    field(:routing, :routing, description: "The instance's maps routing configuration")
   end
 
   @desc """
-  Instance tiles configuration
+  Instance map tiles configuration
   """
   object :tiles do
     field(:endpoint, :string, description: "The instance's tiles endpoint")
     field(:attribution, :string, description: "The instance's tiles attribution text")
   end
 
+  @desc """
+  Instance map routing configuration
+  """
+  object :routing do
+    field(:type, :routing_type, description: "The instance's routing type")
+  end
+
+  enum :routing_type do
+    value(:openstreetmap, description: "Redirect to openstreetmap.org's direction endpoint")
+    value(:google_maps, description: "Redirect to Google Maps's direction endpoint")
+  end
+
   @desc """
   Instance anonymous configuration
   """
diff --git a/lib/mobilizon/config.ex b/lib/mobilizon/config.ex
index 87ad8ce5c..600ae63c8 100644
--- a/lib/mobilizon/config.ex
+++ b/lib/mobilizon/config.ex
@@ -151,6 +151,10 @@ defmodule Mobilizon.Config do
   def instance_maps_tiles_attribution,
     do: Application.get_env(:mobilizon, :maps)[:tiles][:attribution]
 
+  @spec instance_maps_routing_type :: atom()
+  def instance_maps_routing_type,
+    do: Application.get_env(:mobilizon, :maps)[:routing][:type]
+
   @spec anonymous_participation? :: boolean
   def anonymous_participation?,
     do: Application.get_env(:mobilizon, :anonymous)[:participation][:allowed]
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 000000000..fb57ccd13
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,4 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+