diff --git a/front/public/index.html b/front/public/index.html
index 720aeb1c0688f5e4d8fa2f1060e7603b8d81d49e..142419ca63f3295dadbf8773931f2cbe7e37e1cc 100644
--- a/front/public/index.html
+++ b/front/public/index.html
@@ -9,7 +9,7 @@
   <title>Funkwhale</title>
 </head>
 
-<body class="theme-dark">
+<body class="theme-light" id="body">
   <noscript>
     <strong>We're sorry but Funkwhale doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
   </noscript>
diff --git a/front/src/App.vue b/front/src/App.vue
index fd94a9f4605dc69d386d864f3663c5d928e8e4e8..1ecb49cc130c3be6f12f246283142b1fc701a893 100644
--- a/front/src/App.vue
+++ b/front/src/App.vue
@@ -227,6 +227,14 @@ export default {
       this.$store.dispatch('instance/fetchSettings')
       this.fetchNodeInfo()
     },
+    '$store.state.ui.theme': {
+      immediate: true,
+      handler (newValue, oldValue) {
+        let body = document.getElementById('body')
+        body.classList.remove(`theme-${oldValue}`)
+        body.classList.add(`theme-${newValue}`)
+      },
+    },
     '$store.state.auth.authenticated' (newValue) {
       if (!newValue) {
         this.disconnect()
diff --git a/front/src/components/Footer.vue b/front/src/components/Footer.vue
index 5e3c67462f00fcbf81461ccac6ea46e0b84bac52..8a66fa998b76d693f8f4d0be21555e1c85527121 100644
--- a/front/src/components/Footer.vue
+++ b/front/src/components/Footer.vue
@@ -33,6 +33,14 @@
             <a href="https://docs.funkwhale.audio/users/apps.html" class="item" target="_blank"><translate translate-context="Footer/*/List item.Link">Mobile and desktop apps</translate></a>
             <div role="button" class="item" @click="$emit('show:shortcuts-modal')"><translate translate-context="Footer/*/List item.Link/Short, Noun">Keyboard shortcuts</translate></div>
           </div>
+          <div class="ui form">
+            <div class="ui field">
+              <label><translate translate-context="Footer/Settings/Dropdown.Label/Short, Verb">Change theme</translate></label>
+              <select class="ui dropdown" :value="$store.state.ui.theme" @change="$store.commit('ui/theme', $event.target.value)">
+                <option v-for="theme in themes" :key="theme.key" :value="theme.key">{{ theme.name }}</option>
+              </select>
+            </div>
+          </div>
         </section>
         <section class="four wide column">
           <h4 v-translate class="ui header">Getting help</h4>
@@ -76,6 +84,18 @@ export default {
       parser.href = url
       return parser.hostname
     },
+    themes () {
+      return [
+        {
+          name: this.$pgettext('Footer/Settings/Dropdown.Label/Theme name', 'Light'),
+          key: 'light'
+        },
+        {
+          name: this.$pgettext('Footer/Settings/Dropdown.Label/Theme name', 'Dark'),
+          key: 'dark'
+        }
+      ]
+    }
   }
 }
 </script>
diff --git a/front/src/store/index.js b/front/src/store/index.js
index e46aea86de226a678eaa27c0666249a44a526941..3a90b7146119e66ec711f8f529fb79f55472504d 100644
--- a/front/src/store/index.js
+++ b/front/src/store/index.js
@@ -40,7 +40,7 @@ export default new Vuex.Store({
     }),
     createPersistedState({
       key: 'ui',
-      paths: ['ui.currentLanguage', 'ui.momentLocale']
+      paths: ['ui.currentLanguage', 'ui.momentLocale', 'ui.theme']
     }),
     createPersistedState({
       key: 'radios',
diff --git a/front/src/store/ui.js b/front/src/store/ui.js
index cec9ef9c568b39459495bc73c4c23eb46c449500..b0013096549eb4c04e3aa46b931252c4c75babba 100644
--- a/front/src/store/ui.js
+++ b/front/src/store/ui.js
@@ -10,6 +10,7 @@ export default {
     maxMessages: 100,
     messageDisplayDuration: 10000,
     messages: [],
+    theme: 'light',
     notifications: {
       inbox: 0,
       pendingReviewEdits: 0,
@@ -38,6 +39,9 @@ export default {
     computeLastDate: (state) => {
       state.lastDate = new Date()
     },
+    theme: (state, value) => {
+      state.theme = value
+    },
     addMessage (state, message) {
       state.messages.push(message)
       if (state.messages.length > state.maxMessages) {