logo
cd ..

How to Create a Custom 404 Error Page in Nextjs 13

Comments
4 min

How to Create a Custom 404 Error Page in Nextjs 13

Learn how to create a custom 404 Error page in Next.js 13 app directory to handle all unmatched URLs and for nested routes using the not-found.js file

How to Create a Custom 404 Page in Next.js 13

Creating a custom 404 page in Next.js isn't as straightforward and restricted as it used to be, especially with the recent changes introduced in Next.js 13, the process has become more flexible and powerful, allowing for a more nuanced approach to handling errors and improving user experience.

In this article, we'll explore how to create a custom 404 error page that catches any unmatched URLs in your next app and then I'll show you how you can set up this error page in nested routes to display a different error page from the one on the root using the not-found.js file.

If you want to learn how to build a custom 404 page in older versions of nextjs, check out my other article on how to create a custom 404 page in nextjs .

Overview

Unlike next 12 that uses a static default 404 page, next 13 makes use of a file called not-found.js.

According to the nextjs docs: The not-found.js file is used to render UI when the notFound function is thrown within a route segment. (nextjs.org, 2023)

This file is a server component by default and it supports data fetching.

To get started, we'll first explore how to setup this 404 page to handle all unmatched URLs in your app:

Not-found in App Root

The root app/not-found.js file handles all unmatched URLs for your whole application; this means users who visits a URL that does not exist on your app will be shown the UI exported by the app/not-found.js file.

To get started, create a not-found.js file inside your app directory. Here's a typical markup that can be used in this file:

app/not-found.tsx

import Link from "next/link";

export default function NotFound() {
  return (
    <main>
      <h1>Error 404 šŸ˜„</h1>
      <p>Oops! This page was not found</p>
      <Link href="/">
        Return Home
      </Link>
    </main>
  );
}

You can style this component just like every other component in nextjs. Above, I'm simply adding some styles via the global.css file.

Once added, try visiting any route that does not exist within your app and it should redirect to this component.

Custom notfound page
not-found page on the app root

Aside from creating an error route, the not-found.js file also provides a built-in function called notFound() that triggers the not-found component when it is called within a route segment. Let's discuss that in the next section

Not-found in Route Segments

This works by importing the notFound module from "next/navigation" and calling the function within the dynamic segment. Let's say you have a dynamic route that results in individual blog posts: blog/a, blog/b, you can catch errors within the dynamic route and display a separate not-found.js file from the one defined in the root.

This is what the folder structure would look like:

file tree

app/
ā””ā”€ā”€ blog/
    ā”œā”€ā”€ [slug]/
    ā”‚   ā”œā”€ā”€ page.tsx
    ā”‚   ā””ā”€ā”€ not-found.tsx
    ā””ā”€ā”€ page.tsx

First, we have a blog directory that contains a dynamic route (slug) for individual posts, and then the not-found.js file that should be triggered for only the nested slug component.

Here's the markup for the nested not-found.js file:

app/blog/[slug]/not-found.tsx

"use client";

import Link from "next/link";
import { usePathname } from "next/navigation";

export default function NotFoundComponent() {
  const path = usePathname();

  return (
    <main className="container">
      <h1>{`"${path}"`} Not Found šŸ“–</h1>
      <p>Oops! We could not find this post.</p>
      <Link href="/blog" className="button">
        Return To Blog
      </Link>
    </main>
  );
}
usePathname is a Client Component hook that lets you read the current URL's path name.

To demonstrate how this will work, here's a list of links that should route to individual posts via the [slug] parameter.

app/blog/page.tsx

import Link from "next/link";

export default function Blog() {
  return (
    <main>
      <h1>Blog</h1>
      <Link href="/blog/a">Post A</Link>
      <Link href="/blog/b">Post B</Link>
      <Link href="/blog/cc">Post C</Link>
    </main>
  );
}

Within the dynamic component, you can import the notFound module from "next/navigation" and call the function based on any condition of your choosing:

app/blog/[slug]/page.tsx

import Link from "next/link";
import { notFound } from "next/navigation";

export default function Post({ params }: { params: { slug: string } }) {
  if (params.slug.length > 1) {
    notFound();
  }

  return (
    <div>
      <h1>Post Slug: {params.slug} šŸ“–</h1>
      <p>
        Lorem, ipsum dolor sit amet consectetur adipisicing elit. Delectus,
        dicta.
      </p>
      <Link href="/blog">
        Return To Blog
      </Link>
    </div>
  );
}

In the example above, the function is been called whenever the post slug length is greater than 1. Since /blog/cc matches this condition, when you navigate to its URL, you will get the not-found error.

not-found.js in nested route
not-found.js in nested route

This is just an example to showcase how the notFound function works. A more valid use case for calling this function would be when a post is missing or unavailable.

Important things to note about the not-found.js component

  • This component does not accept any props
  • This is a server component by default but it can be converted to a client component using the "use client" flag.
  • You can mark the component as async and fetch content to display on it: Here's my example implementation that fetches my featured posts and displays them.

To test if you've been following this article, see if you can answer the following questions

[@portabletext/react] Unknown block type "quiz", specify a component for it in the `components.types` prop

Conclusion

Although it is not explicit in the nextjs documentation whether the not-found.js file is the official way of creating a custom 404 page in nextjs 13, the techniques explored in this article should serve as a good foundation. As Next.js continues to evolve, especially with the stable release of the app directory, we can anticipate further advancements and refinements, particularly in the realm of routing errors and 404 pages

I hope this article has provided valuable insights to you. If you have any questions or feedback, feel free to reach out. Happy coding!

References:

Code Files - GitHub

Nextjs. (2023). notFound. https://nextjs.org/docs/app/api-reference/functions/not-found . Functions.

Nextjs. (2023). not-found.js. https://nextjs.org/docs/app/api-reference/functions/not-found . File Conventions.

Comments

Support

Do you feel like supporting my work? šŸ™‚Buymeacoffee button