
Creating a Custom 404 Page in Next.js
- Author: Md. Saad
- Published at: June 09, 2024
- Updated at: June 09, 2024
In the faster world of web development, Next.js has introduced many new features that simplify your web experience. Such a feature is handling unmatched routes in your application. Next.js has added a simple, straightforward forward and developer-friendly process for creating a custom 404 page. In this post, I'll explain how to make a custom 404 error page that detects any mismatched URLs in your upcoming application. Later we will discuss the deeper functionalities of the error page in Next.js.
Create A Next.js App
The first and foremost step, to begin with, is creating a Next.js App. Use the following command to create a next.js app.
npx create-next-app@latest app-name
As it is not an article on creating the next.js app, we will not discuss it in detail. If you want to read it in detail follow the link.
Add not-found.jsx
Whenever we go to any unmatched route, next.js takes us to a default 404 page. This will look like the following image.

However, we can easily customize this. All you have to do is create a not-found.jsx file in the app folder and it will automatically manage requests to a URL that doesn't have a corresponding route in your app. Let’s create a not-found.jsx file inside your app directory. Here's a basic markup that can be used in this file:
import Link from "next/link";
const NotFound = () => {
return (
<section className="mb-150 pt-[200px]">
<div className="container mx-auto">
<div className=" text-center">
<h1 className="from-0 to-primary/0 bg-gradient-to-b from-[red] to-90% bg-clip-text text-[140px] font-bold leading-[1] text-transparent dark:text-transparent">
404
</h1>
<p className="text-2xl font-semibold -mt-16">Error</p>
<h2 className="mb-9 text-[64px] font-bold leading-[1.22]">
Oops! <br />
Page Not Found
</h2>
<p className="mb-8 text-xl">
This page doesn’t exist or was removed! <br />
We suggest you go back to home.
</p>
<Link
href="/"
className="bg-gray-800 py-5 px-6 rounded-xl"
>
Go Back-Home
</Link>
</div>
</div>
</section>
);
};
export default NotFound;
You can style the components just like the other next.js components. I have used Tailwind here to style the file. You can read more about setting tailwind CSS on your site on this link.
Note: You can pass over whatever message you want inside the not-found.jsx file. I have added these codes to give examples only.
After successfully adding these codes, run your build process with
npm run dev.
Your site will be opened on localhost:3000. Now, try to visit any unmatched route within your app and it should redirect you to the newly not-found.jsx component. And it should look like this:

Data Fetching on not-found.jsx
By default, not-found.jsx is generated through the server as it is a Server Component. Thus, You can use an async function to fetch and display data. A simple example is attached below:
import Link from 'next/link'
import { headers } from 'next/headers'
export default async function NotFound() {
const headersList = headers()
const domain = headersList.get('host')
const data = await getSiteData(domain)
return (
<div>
<h2>Not Found: {data.name}</h2>
<p>Could not find requested resource</p>
<p>
View <Link href="/blog">all posts</Link>
</p>
</div>
)
}
Use not-found.jsx as Client Components
Though not-found.jsx is a server component, we can easily transform it into a client component. If an error with the path name needs to be shown, you have to convert it into client components by declaring “use client” and using Client Component hooks like usePathname to display content based on the path. A simple example is attached below:
"use client";
import Link from "next/link";
import {usePathname} from "next/navigation";
const NotFound = () => {
const pathname = usePathname();
return (
<section className="mb-150 pt-[200px]">
<div className="container mx-auto">
<div className=" text-center">
<h1 className="from-0 to-primary/0 bg-gradient-to-b from-[red] to-90% bg-clip-text text-[140px] font-bold leading-[1] text-transparent dark:text-transparent">
404
</h1>
<p className="text-2xl font-semibold -mt-16">Error</p>
<h2 className="mb-9 text-[64px] font-bold leading-[1.22]">
Oops! <br />
{pathname} Page Not Found
</h2>
<p className="mb-8 text-xl">
This page doesn’t exist or was removed! <br />
We suggest you go back to home.
</p>
<Link
href="/"
className="bg-gray-800 py-5 px-6 rounded-xl"
>
Go Back-Home
</Link>
</div>
</div>
</section>
);
};
export default NotFound;
Now, when you go to an unmatched route such as localhost:3000/error, you should have seen the following error:

not-found.jsx in Sub Folder
We can also add separate not-found.jsx for each segment route. For example:
- create products folder
- Inside it create another [id] folder
- Now create a page.jsx file.
Your folder structure should look like this:
app/
└── products/
├── [id]/
│ ├── page.jsx
│ └── not-found.jsx
Now add the following codes to the page.jsx file:
import {notFound} from "next/navigation";
export default function Products({params}) {
const {id} = params;
if (id > 4) {
notFound();
}
return (
<section className="mb-150 pt-[200px]">
<div className="container mx-auto">
<div className=" text-center">
<h1 className="from-0 to-primary/0 bg-gradient-to-b from-[white] to-100% bg-clip-text text-[140px] font-bold leading-[1] text-transparent">
Products {id}
</h1>
</div>
</div>
</section>
);
}Within the page.jsx, import the notFound module from "next/navigation" and call the function based on any condition. Here, I have created a function that will call the notFound function wherever the post id length is greater than 4. As a result, /products/5 URL will throw a not-found error.
However, at this moment the /products/[id] is using the root not-found.jsx to show the error messages. Now, it is time to change that and show a different error message for this subfolder only.
Let’s create a not-found.jsx file inside /products/[id] folder. And add the following codes:
"use client";
import Link from "next/link";
import {usePathname} from "next/navigation";
const ReviewNotFound = () => {
const pathname = usePathname();
return (
<section className="mb-150 pt-[200px]">
<div className="container mx-auto">
<div className=" text-center">
<h1 className="from-0 to-primary/0 bg-gradient-to-b from-[red] to-100% bg-clip-text text-[140px] font-bold leading-[1] text-transparent dark:text-transparent">
Something is Wrong
</h1>
<p className="text-2xl font-semibold -mt-16">{pathname}</p>
<h2 className="mb-9 text-[64px] font-bold leading-[1.22]">
Page in the Products List <br /> Are Not Available
</h2>
<Link
href="/"
className="bg-gray-800 py-5 px-6 rounded-xl"
>
Go Back-Home
</Link>
</div>
</div>
</section>
);
};
export default ReviewNotFound;
Now, whenever you run the code and go to the products whose ID is more than 4 like /products/10, you will see the following error message.

Boom!! I have gone through almost all the possible scenarios of adding error messages using not-found.jsx in next.js. I hope you gathered some insightful information from this article. Feel free to get in touch with Staticmania if you have any queries or comments. Enjoy your coding!

Adding eCommerce Functionality in Hugo with Snipcart
In today's digital age, establishing an online presence for your business is essential to reach a broader customer base and increase revenue
Read article