NextJS Redirect Without Flashing Content
Jasser Mark Arioste
Hello hustlers. In this tutorial, you’ll learn how to use a server-side redirect to prevent the flashing of content for unauthenticated users. We’ll use NextJS Middleware along with the next-auth package for authentication.
Prerequisites
This guide assumes the following:
- You’re using NextJS v12.3.4 and above. This gives us the best middleware functionality.
- You’re using next-auth v4.17 and above.
Problem with Static Pages
If you’re using next-auth and you have static pages in your app, you can only get the session from the client-side. Sometimes, this creates a delay in getting the user and shows flashing content if not implemented properly:
import { NextPage } from "next";
import { signOut, useSession } from "next-auth/react";
import React from "react";
const HomePage: NextPage = () => {
const { data } = useSession();
if (!data?.user) {
return <div>Unauthorized - 403. Please login</div>;
}
return (
<div>
<h1>Home Page</h1>
<p>You are logged in as {data?.user?.email} </p>
</div>
);
};
export default HomePage;
Another problem with this approach is that we have to add this logic to every page that needs authentication.
This flashing doesn’t occur in server-side generated pages since we can check the session inside getServerSideProps and redirect to the login page as necessary:
Inside a page component:
// pages/admin.tsx
import { GetServerSideProps } from "next";
import { getSession, useSession } from "next-auth/react";
import { GetServerSideProps } from "next";
import { getSession, useSession } from "next-auth/react";
import React from "react";
const AdminPage = () => {
const { data } = useSession();
if (!data?.user) {
return <div>Unauthorized - 403. Please login</div>;
}
return <div>AdminPage</div>;
};
export default AdminPage;
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getSession({ req: ctx.req });
if (!session) {
return {
redirect: {
destination: "/login",
permanent: false,
},
};
}
return {
props: {
session,
},
};
};
Inside _app.tsx :
import "../styles/globals.css";
import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";
function MyApp({ Component, pageProps }: AppProps) {
const { session, ...restPageProps } = pageProps;
return (
<SessionProvider session={session}>
<Component {...restPageProps} />
</SessionProvider>
);
}
export default MyApp;
This prevents flashing the unauthorized content since the session is provided via props and the client does not have to make a request using /api/auth/session . The problem with this approach is that, you’ll have to add this logic for every protected page in your application.
How can we improve on this?
The Solution
Since NextJS v12+, we have the ability to process the incoming request before returning the generated page (static or server-side generated).
Create a middleware.ts file at the root directory of your project and add this logic here:
// middldware.ts
import { getToken } from "next-auth/jwt";
import { NextRequest, NextResponse } from "next/server";
export async function middleware(req: NextRequest) {
const pathname = req.nextUrl.pathname;
const protectedPaths = ["/", "/admin"];
const isPathProtected = protectedPaths?.some((path) => pathname == path);
const res = NextResponse.next();
if (isPathProtected) {
const token = await getToken({ req });
if (!token) {
const url = new URL(`/login`, req.url);
url.searchParams.set("callbackUrl", pathname);
return NextResponse.redirect(url);
}
}
return res;
}
Demo and Code
The demo is available at Vercel and the full code is available on GitHub .
Conclusion
We learned how to redirect without flashing content by using NextJS middleware. Middleware is a very powerful feature in NextJS and there’s a lot we can do to process the incoming request.
If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on Twitter .
What’s Next?
- Add role-based authorization for your NextJS app . Differentiate normal users from admin users and what pages they can access.
- Implement middleware chaining/stacking. Organize your middleware functions like a pro.


