diff --git a/aleksis/core/frontend/components/app/ErrorPage.vue b/aleksis/core/frontend/components/app/ErrorPage.vue
index abfb51fd08aad58aaed196b84aba8acf906964c9..6ee111e5d7b573cbea45530fb73078d4fcc076e8 100644
--- a/aleksis/core/frontend/components/app/ErrorPage.vue
+++ b/aleksis/core/frontend/components/app/ErrorPage.vue
@@ -5,7 +5,7 @@
   >
     <h1 class="text-h2">{{ $t(shortErrorMessageKey) }}</h1>
     <div>{{ $t(longErrorMessageKey) }}</div>
-    <v-btn color="secondary" :to="{ name: redirectRouteName }">
+    <v-btn color="secondary" :to="{ name: redirectRouteName }" v-if="!hideButton">
       <v-icon left>{{ redirectButtonIcon }}</v-icon>
       {{ $t(redirectButtonTextKey) }}
     </v-btn>
@@ -36,6 +36,11 @@ export default {
       type: String,
       required: true,
     },
+    hideButton: {
+      type: Boolean,
+      default: false,
+      required: false,
+    },
   },
 };
 </script>
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 8b3148771b2310d455228911189712340a4ebb7c..1f62450df2f2278426617a90d5f1a41fd02afde9 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -199,6 +199,7 @@ TEMPLATES = [
                 "maintenance_mode.context_processors.maintenance_mode",
                 "dynamic_preferences.processors.global_preferences",
                 "aleksis.core.util.core_helpers.custom_information_processor",
+                "aleksis.core.util.context_processors.need_maintenance_response_context_processor",
             ],
         },
     },
@@ -697,7 +698,7 @@ MAINTENANCE_MODE = _settings.get("maintenance.enabled", None)
 MAINTENANCE_MODE_IGNORE_IP_ADDRESSES = _settings.get(
     "maintenance.ignore_ips", _settings.get("maintenance.internal_ips", [])
 )
-MAINTENANCE_MODE_GET_CLIENT_IP_ADDRESS = "ipware.ip.get_ip"
+MAINTENANCE_MODE_GET_CLIENT_IP_ADDRESS = "aleksis.core.util.core_helpers.get_ip"
 MAINTENANCE_MODE_IGNORE_SUPERUSER = True
 MAINTENANCE_MODE_STATE_FILE_NAME = _settings.get(
     "maintenance.statefile", "maintenance_mode_state.txt"
diff --git a/aleksis/core/templates/503.html b/aleksis/core/templates/503.html
index 21578e63238f09081e35081b4ed45cf1e0a47a1c..ba7cb4005cfc084338f451db643c2268d45f634b 100644
--- a/aleksis/core/templates/503.html
+++ b/aleksis/core/templates/503.html
@@ -1,21 +1,4 @@
-{% extends "core/base.html" %}
-{% load i18n %}
+{% extends "core/vue_index.html" %}
 
-
-{% block content %}
-  <div class="container">
-    <div class="card red">
-      <div class="card-content white-text">
-        <i class="material-icons iconify small left" data-icon="mdi:alert-octagon-outline"></i>
-        <span class="card-title">{% blocktrans %}The maintenance mode is currently enabled. Please try again
-          later.{% endblocktrans %}</span>
-        <p>
-          {% blocktrans %}
-            This page is currently unavailable. If this error persists, contact your site administrators:
-          {% endblocktrans %}
-        </p>
-        {% include "core/partials/admins_list.html" %}
-      </div>
-    </div>
-  </div>
+{% block no_frontend %}
 {% endblock %}
diff --git a/aleksis/core/templates/core/partials/splash_screen.html b/aleksis/core/templates/core/partials/splash_screen.html
index f3491141c1d0bb48b1b767e382ce66ff87239936..10969c261082120648f4b682d2678ba0fee7977f 100644
--- a/aleksis/core/templates/core/partials/splash_screen.html
+++ b/aleksis/core/templates/core/partials/splash_screen.html
@@ -12,13 +12,23 @@
       This webbrowser doesn't support JavaScript, or its execution is blocked. Please use another browser to continue.
     {% endblocktrans %}
   </noscript>
+{% if need_maintenance_response %}
+  <p>
+    {% blocktrans %}
+      The maintenance mode is currently enabled. Please try again later.
+    {% endblocktrans %}
+  </p>
+{% endif %}
 </div>
+
+{% if not need_maintenance_response %}
 <div class="lds-ellipsis">
   <div></div>
   <div></div>
   <div></div>
   <div></div>
 </div>
+{% endif %}
 
 <style>
   #logo {
@@ -36,7 +46,7 @@
     max-height: calc(100vh - 10vh - calc(2 * min(85px, 15vh)));
   }
 
-  noscript {
+  noscript, p {
     font-family: Roboto, sans-serif;
     font-weight: 400;
   }
diff --git a/aleksis/core/templates/core/vue_index.html b/aleksis/core/templates/core/vue_index.html
index b39da47ea2154318d13ce0d60428f175299ee562..f2c914327ca849801172e8816297eedd724bb99d 100644
--- a/aleksis/core/templates/core/vue_index.html
+++ b/aleksis/core/templates/core/vue_index.html
@@ -29,6 +29,10 @@
       <app ref="aleksisApp"></app>
     </main>
 
-    {% vite_asset 'aleksis/core/frontend/index.js' %}
+    {% block no_frontend %}
+      {% if not need_maintenance_response %}
+        {% vite_asset 'aleksis/core/frontend/index.js' %}
+      {% endif %}
+    {% endblock no_frontend %}
   </body>
 </html>
diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py
index d43c3a920447a7db11f599e53c8795cf36ce4859..00286829a4fc09d6bf8e2da4a44733281a749f98 100644
--- a/aleksis/core/urls.py
+++ b/aleksis/core/urls.py
@@ -11,6 +11,7 @@ import calendarweek.django
 from ckeditor_uploader import views as ckeditor_uploader_views
 from graphene_django.views import GraphQLView
 from health_check.urls import urlpatterns as health_urls
+from maintenance_mode.decorators import force_maintenance_mode_off
 from oauth2_provider.views import ConnectDiscoveryInfoView
 from rules.contrib.views import permission_required
 from two_factor.urls import urlpatterns as tf_urls
@@ -24,7 +25,7 @@ urlpatterns = [
     path(settings.MEDIA_URL.removeprefix("/"), include("titofisto.urls")),
     path("__icons__/", include("dj_iconify.urls")),
     path("graphql/", csrf_exempt(GraphQLView.as_view(graphiql=True)), name="graphql"),
-    path("logo", views.LogoView.as_view(), name="logo"),
+    path("logo", force_maintenance_mode_off(views.LogoView.as_view()), name="logo"),
     path(
         ".well-known/openid-configuration/",
         ConnectDiscoveryInfoView.as_view(),
diff --git a/aleksis/core/util/context_processors.py b/aleksis/core/util/context_processors.py
new file mode 100644
index 0000000000000000000000000000000000000000..acaf79cc7adf9f24b508bb96cd78c65d2a19a2f3
--- /dev/null
+++ b/aleksis/core/util/context_processors.py
@@ -0,0 +1,5 @@
+from maintenance_mode.http import need_maintenance_response
+
+
+def need_maintenance_response_context_processor(request):
+    return {"need_maintenance_response": need_maintenance_response(request)}
diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index 511b6ada19c8ee3bc984ffef7865443142319888..c7f89fb5badfbca1e5014b78a150129afd990669 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -482,3 +482,10 @@ class OOTRouter:
 
 
 post_invalidation.connect(OOTRouter._invalidate_cachalot)
+
+
+def get_ip(*args, **kwargs):
+    """Recreate ipware.ip.get_ip as it was replaced by get_client_ip."""
+    from ipware.ip import get_client_ip  # noqa
+
+    return get_client_ip(*args, **kwargs)[0]
diff --git a/aleksis/core/vite.config.js b/aleksis/core/vite.config.js
index bf029ce617723720448c6376688bcf392a4eebab..aba13604379a5f1512cce5907c7960fde9291922 100644
--- a/aleksis/core/vite.config.js
+++ b/aleksis/core/vite.config.js
@@ -236,6 +236,16 @@ export default defineConfig({
                   "PWA-Is-Cacheable": "true",
                 },
               },
+              plugins: [
+                {
+                  fetchDidSucceed: async ({ request, response }) => {
+                    if (response.ok) {
+                      return response;
+                    }
+                    throw new Error(`${response.status} ${response.statusText}`);
+                  },
+                }
+              ],
             },
           },
           {