diff --git a/front/src/App.vue b/front/src/App.vue
index 6900ccaf8dbecf01b6def1dd2df894961987990d..b6bec0edef7f17832d71b9bc7928443f4204a902 100644
--- a/front/src/App.vue
+++ b/front/src/App.vue
@@ -11,16 +11,7 @@
     <template>
       <sidebar></sidebar>
       <set-instance-modal @update:show="showSetInstanceModal = $event" :show="showSetInstanceModal"></set-instance-modal>
-      <service-messages>
-        <message key="refreshApp" class="large info" v-if="serviceWorker.updateAvailable">
-          <p>
-            <translate translate-context="App/Message/Paragraph">A new version of the app is available.</translate>
-          </p>
-          <button class="ui basic button" @click.stop="updateApp">
-            <translate translate-context="App/Message/Button">Update</translate>
-          </button>
-        </message>
-      </service-messages>
+      <service-messages></service-messages>
       <transition name="queue">
         <queue @touch-progress="$refs.player.setCurrentTime($event)" v-if="$store.state.ui.queueFocused"></queue>
       </transition>
@@ -263,6 +254,7 @@ export default {
       parts.push(this.$store.state.instance.settings.instance.name.value || 'Funkwhale')
       document.title = parts.join(' – ')
     },
+
     updateApp () {
       this.$store.commit('ui/serviceWorker', {updateAvailable: false})
       if (!this.serviceWorker.registration || !this.serviceWorker.registration.waiting) { return; }
@@ -380,6 +372,35 @@ export default {
         this.updateDocumentTitle()
       },
     },
+    'serviceWorker.updateAvailable': {
+      handler (v) {
+        if (!v) {
+          return
+        }
+        let self = this
+        this.$store.commit('ui/addMessage', {
+          content: this.$pgettext("App/Message/Paragraph", "A new version of the app is available."),
+          date: new Date(),
+          key: 'refreshApp',
+          displayTime: 0,
+          classActions: 'bottom attached',
+          actions: [
+            {
+              text: this.$pgettext("App/Message/Paragraph", "Update"),
+              class: "primary",
+              click: function () {
+                self.updateApp()
+              },
+            },
+            {
+              text: this.$pgettext("App/Message/Paragraph", "Later"),
+              class: "basic",
+            }
+          ]
+        })
+      },
+      immediate: true,
+    }
   }
 }
 </script>
diff --git a/front/src/store/ui.js b/front/src/store/ui.js
index f6346d6f858bfd74a7fc93cc6658c5bb5c8f228f..3e481917ae3a45a4b8070e7e2f734c0d78588cc6 100644
--- a/front/src/store/ui.js
+++ b/front/src/store/ui.js
@@ -190,6 +190,10 @@ export default {
         key: String(new Date()),
         ...message,
       }
+      let key = finalMessage.key
+      state.messages = state.messages.filter((m) => {
+        return m.key != key
+      })
       state.messages.push(finalMessage)
       if (state.messages.length > state.maxMessages) {
         state.messages.shift()