How to set up Maintenance page for next js application hosted on vercel without having to redeploy

1.1k Views Asked by At

Anyone know an implementation of a Maintenance page similar to this enter image description here for a next.js application that wont require changing .env variables and redeploying each time site is switched on and off?

I would like to use an API response e.g siteStatus === 'down' or siteStatus === 'up' to set the maintenance page up.

I would appreciate any input on this because I have been stuck on it for a long time.

2

There are 2 best solutions below

0
Igor Danchenko On

Changing the environment variable and redeploying the app is probably not a high price to pay considering the disadvantages of alternative approaches.

Here are some ideas and their disadvantages:

  1. Implement getInitialProps in the _app, but you are going to lose static pages optimization.
  2. Implement getStaticProps in all your pages (you can add a HOC to streamline this process), and revalidate let's say every 10 minutes. But that would be an enormous overhead due to constant revalidation.
  3. Wrap your pages with MaintenanceGuard component in the _app that would delay rendering on the client until it fetches maintenance status. This approach would negatively affect time-to-interactive and UX in general.

Now, I can see an acceptable implementation option if you can migrate your app to the Next 13 app directory.

You'll need an external API endpoint hosted outside your app that would respond with maintenance status.

You can check maintenance status in the root layout of your app and conditionally display maintenance notification as follows.

// app/layout.tsx

import * as React from "react";

async function fetchMaintenance() {
  const response = await fetch(`${process.env.MAINTENANCE_ENDPOINT}`, {
    next: { tags: ["maintenance"] },
  });
  const data = await response.json();
  return data.maintenance;
}

export default async function RootLayout({
  children,
}: React.PropsWithChildren) {
  const maintenance = await fetchMaintenance();

  return (
    <html lang="en">
      <body>{!maintenance ? children : <h1>Scheduled Maintenance</h1>}</body>
    </html>
  );
}

To perform on-demand revalidation, you can create an API route that would trigger revalidation. To trigger revalidation, send a POST request to YOUR_HOST/api/maintenance endpoint.

// app/api/maintenance/route.ts

import { NextResponse } from "next/server";
import { revalidateTag } from "next/cache";

export async function POST() {
  // TODO: secure this endpoint with appropriate authentication
  revalidateTag("maintenance");
  return NextResponse.json({ revalidated: true, now: Date.now() });
}
1
woywro On

You can try https://www.npmjs.com/package/next-maintenance-mode. It allows to choose from edge-config and upstash providers. It features caching what means that you'll also save on provider's bandwidth usage.