diff --git a/src/main.js b/src/main.js
index 3f0f6824e4fdd54ca50941682ee96bce295ccde6..917fdaea24e97b736a4b0d4288f8dead67f7d32c 100644
--- a/src/main.js
+++ b/src/main.js
@@ -30,16 +30,16 @@ const navigation = {
                 path: "/menu/call/emergency",
                 message: "Calling Emergency",
               },
-              contact1: {
+              contacta: {
                 label: "Flute Inc.",
-                command: "contact A",
-                path: "/menu/call/contact1",
+                command: "contact a",
+                path: "/menu/call/contacta",
                 message: "Calling Flute Inc.",
               },
-              contact2: {
+              contactb: {
                 label: "Brays AG",
-                command: "contact B",
-                path: "/menu/call/contact2",
+                command: "contact b",
+                path: "/menu/call/contactb",
                 message: "Calling Brays AG",
               },
             },
@@ -203,6 +203,10 @@ function buildPageContents(object) {
     const navigationEl = document.getElementById("navigation");
     navigationEl.replaceChildren(listEl);
 
+    // dispatch custom event to listen for menu updates
+    const updated = new CustomEvent("updated");
+    navigationEl.dispatchEvent(updated);
+
     // auto select first item
     // focusNavigationItem(1);
 
@@ -337,6 +341,16 @@ function addMouseControls() {
     }
   });
 
+  // unfocus all items
+  appEl.addEventListener("mouseout", (event) => {
+    const listItem = event.target.closest("li.link");
+    if (listItem) {
+      // unselect all items
+      const navigationList = document.querySelectorAll("#navigation li");
+      for (let item of navigationList) delete item.dataset.selected;
+    }
+  });
+
   // select on mouseclick
   appEl.addEventListener("click", (event) => {
     event.preventDefault();
@@ -370,10 +384,8 @@ function addButtonControls() {
       event.code === "ArrowRight" ||
       event.code === "ArrowDown" ||
       event.code === "ArrowLeft"
-    ) {
+    )
       event.preventDefault();
-      printLogMsg("key: " + event.code);
-    }
 
     // browsing navigation items
     if (event.code === "Tab" || event.code === "ArrowDown")
@@ -425,23 +437,23 @@ function addButtonControls() {
 // add voice controls
 // ===================
 function addVoiceControls() {
+  // voice controls only work on google chrome!
   var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
   var SpeechGrammarList = SpeechGrammarList || window.webkitSpeechGrammarList;
   var SpeechRecognitionEvent =
     SpeechRecognitionEvent || webkitSpeechRecognitionEvent;
 
-  var commands = [
-    "menu",
-    "call",
-    "check",
-    "apps",
-    "open",
-    "back",
-    "close",
-    "exit",
-  ];
-
-  var recognition = new SpeechRecognition();
+  let availableCommands = [];
+  let commands = [];
+  updateVoiceCommandList();
+
+  // listen for menu updates and refresh commands list
+  const navigationEl = document.getElementById("navigation");
+  navigationEl.addEventListener("updated", (event) => {
+    updateVoiceCommandList();
+  });
+
+  let recognition = new SpeechRecognition();
   if (SpeechGrammarList) {
     var speechRecognitionList = new SpeechGrammarList();
     var grammar =
@@ -449,7 +461,7 @@ function addVoiceControls() {
       commands.join(" | ") +
       " ;";
     speechRecognitionList.addFromString(grammar, 1);
-    recognition.grammars = speechRecognitionList;
+    // recognition.grammars = speechRecognitionList;
   }
   recognition.continuous = false;
   recognition.lang = "en-US";
@@ -457,39 +469,56 @@ function addVoiceControls() {
   recognition.maxAlternatives = 1;
 
   recognition.start();
-  printLogMsg("recognition started");
+  printLogMsg("Voice > listening");
 
   recognition.onresult = function (event) {
-    let command = event.results[0][0].transcript;
+    let command = event.results[0][0].transcript.toLowerCase();
     let confidence = event.results[0][0].confidence;
+    command = command.toLowerCase();
+
+    printLogMsg(`Voice > Received "${command}" (${confidence.toFixed(2)})`);
 
     if (commands.includes(command)) {
-      printLogMsg("Received: " + command + ". Confidence: " + confidence);
-
-      if (command === "menu") navigateToPath("/menu");
-      else if (command === "call") navigateToPath("/menu/call");
-      else if (command === "check") navigateToPath("/menu/check");
-      else if (command === "apps") navigateToPath("/menu/apps");
-      else if (command === "open") navigateToSelected();
-      else if (command === "back" || command === "close")
-        moveUpNavigationLevel();
-      else if (command === "exit") navigateToPath("/");
+      let index = commands.indexOf(command); // get index of command in array
+      let path = availableCommands[index].path; // get corresponding path in availableCommands array
+      navigateToPath(path);
     }
   };
 
   recognition.onspeechend = function () {
     recognition.stop();
-    printLogMsg("recognition stopped");
 
     setTimeout(() => {
       recognition.start();
-      printLogMsg("recognition started");
-    }, "1000");
+      printLogMsg("Voice > listening");
+    }, "500");
   };
 
   recognition.onnomatch = function (event) {
     printLogMsg("I didn't recognise that command.");
   };
+
+  // updating voice command list
+  function updateVoiceCommandList() {
+    // search and save currently available voice commands
+    availableCommands = [];
+    const listItems = document.querySelectorAll("a[data-command]");
+    for (let item of listItems) {
+      let command = {
+        command: item.dataset.command,
+        path: item.getAttribute("href"),
+      };
+      availableCommands.push(command);
+    }
+
+    // add custom commands
+    availableCommands.push({ command: "exit", path: "/" });
+    availableCommands.push({ command: "emergency call", path: "/menu/call/emergency" });
+
+    // form commands array for grammarlist
+    commands = availableCommands.map((x) => x.command);
+    printLogMsg(`Voice > Commands: [${commands}]`);
+  }
 }
 
 // printing messages on screen for debugging