Is there a good way to do display a maintenance page when visiting any route of my SvelteKit website?
My app is hosted on Vercel, for those who want to know.
What I've tried so far:
MAINTENANCE_MODE
with a value 1
in Vercel.VITE_MAINTENANCE_MODE
and called with import.meta.env.VITE_MAINTENANCE_MODE
.Then inside +layout.server.js
I have the following code to redirect to /maintenance
route
import { redirect } from "@sveltejs/kit";
export async function load({ url }) {
const { pathname } = url;
// Replace import.meta.env.VITE_MAINTENANCE_MODE with process.env.MAINTENANCE_MODE in Production
if (import.meta.env.VITE_MAINTENANCE_MODE == 1) {
if (pathname == "/maintenance") return;
throw redirect(307, "/maintenance");
} else {
if (pathname == "/maintenance") {
throw redirect(307, "/");
};
};
};
What I've also tried is just throwing an error
in +layout.server.js
with the following:
import { error } from "@sveltejs/kit";
export async function load() {
if (import.meta.env.VITE_MAINTENANCE_MODE == 1) {
throw error(503, "Scheduled for maintenance");
};
};
However this just uses SvelteKit's static fallback error page and not +error.svelte
. I've tried creating src/error.html
in the hope to create a custom error page for +layout.svelte
but couldn't get it to work.
I would like to use a custom page to display "Down for maintenance", but I don't want to create an endpoint for every route in my app to check if the MAINTENANCE_MODE
is set to 1.
Any help is appreciated
You could use a handle
server hook, e.g. src/hooks.server.ts
:
import { env } from '$env/dynamic/private';
import type { Handle } from '@sveltejs/kit';
export const handle: Handle = async ({ event, resolve }) => {
if (env.MAINTENANCE_MODE == '1' && event.route.id != '/maintenance')
return new Response(undefined, { status: 302, headers: { location: '/maintenance' } });
// <other logic>
// Default response
return await resolve(event);
}
And on the maintenance page you can prevent all further navigation:
import { beforeNavigate } from '$app/navigation';
beforeNavigate(async ({ cancel }) => {
cancel();
});
(Possibly add some periodic checks via fetch
calls to navigate elsewhere once the site is back online.)