Skip to main content

Next.js Custom 404 Pages

When users navigate to a page that doesn't exist in your Next.js application, they will see a 404 error page. By default, Next.js provides a basic 404 page, but you can create a custom one to improve user experience, maintain your site's branding, and help users find their way back to existing content.

Introduction to 404 Pages

A 404 page appears when a user tries to access a URL that doesn't exist on your website. Instead of showing a generic error message, a well-designed custom 404 page can:

  • Maintain your site's branding and design language
  • Help users navigate back to important parts of your site
  • Reduce user frustration and bounce rates
  • Provide useful information about why the page wasn't found

Next.js makes it incredibly easy to create custom 404 pages for your application.

Creating a Basic Custom 404 Page

To create a custom 404 page in Next.js, you simply need to create a 404.js or 404.tsx file in your pages directory (for Pages Router) or an equivalent file in your app directory (for App Router).

Using the Pages Router

For Next.js applications using the Pages Router, create a file called 404.js (or 404.tsx for TypeScript) in your pages directory:

jsx
// pages/404.js
import Link from 'next/link'
import styles from '../styles/404.module.css'

export default function Custom404() {
return (
<div className={styles.container}>
<h1>404 - Page Not Found</h1>
<p>Oops! The page you are looking for does not exist.</p>
<Link href="/">
Go back home
</Link>
</div>
)
}

Using the App Router

For Next.js applications using the App Router, create a not-found.js (or not-found.tsx) file in your app directory:

jsx
// app/not-found.js
import Link from 'next/link'

export default function NotFound() {
return (
<div className="not-found-container">
<h1>404 - Page Not Found</h1>
<p>We couldn't find the page you were looking for.</p>
<Link href="/">
Return Home
</Link>
</div>
)
}

Styling Your Custom 404 Page

To make your 404 page match your website's design, you'll want to add styling. You can use CSS modules, styled-components, or any other styling approach you're using in your Next.js project.

Here's an example using CSS modules (for the Pages Router example):

css
/* styles/404.module.css */
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
text-align: center;
padding: 0 20px;
}

.container h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
color: #e53e3e;
}

.container p {
margin-bottom: 2rem;
font-size: 1.2rem;
color: #4a5568;
}

.container a {
padding: 0.75rem 1.5rem;
background-color: #3182ce;
color: white;
border-radius: 0.375rem;
text-decoration: none;
transition: background-color 0.3s;
}

.container a:hover {
background-color: #2b6cb0;
}

Adding Interactive Elements

To make your 404 page more engaging and helpful, you can add interactive elements like a search bar, suggestions for popular pages, or even a funny animation.

Here's an example with a search function and suggested links:

jsx
// pages/404.js
import { useState } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import styles from '../styles/404.module.css'

export default function Custom404() {
const [searchQuery, setSearchQuery] = useState('')
const router = useRouter()

const handleSearch = (e) => {
e.preventDefault()
if (searchQuery.trim()) {
router.push(`/search?q=${encodeURIComponent(searchQuery)}`)
}
}

return (
<div className={styles.container}>
<h1>404 - Page Not Found</h1>
<p>We couldn't find the page you were looking for.</p>

<form onSubmit={handleSearch} className={styles.searchForm}>
<input
type="text"
placeholder="Search for content..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className={styles.searchInput}
/>
<button type="submit" className={styles.searchButton}>Search</button>
</form>

<div className={styles.suggestions}>
<h2>Popular Pages</h2>
<ul>
<li><Link href="/">Home</Link></li>
<li><Link href="/blog">Blog</Link></li>
<li><Link href="/products">Products</Link></li>
<li><Link href="/contact">Contact Us</Link></li>
</ul>
</div>

<Link href="/" className={styles.homeButton}>
Return to Homepage
</Link>
</div>
)
}

Real-World Example: E-commerce 404 Page

Let's create a more practical example for an e-commerce site where the 404 page helps users find products they might be looking for:

jsx
// pages/404.js
import { useState, useEffect } from 'react'
import Link from 'next/link'
import Image from 'next/image'
import { useRouter } from 'next/router'
import styles from '../styles/404.module.css'

export default function Custom404() {
const [featuredProducts, setFeaturedProducts] = useState([])
const router = useRouter()

useEffect(() => {
// In a real app, you might fetch from an API
// This is just mock data for the example
setFeaturedProducts([
{ id: 1, name: 'Wireless Headphones', image: '/images/headphones.jpg', slug: 'wireless-headphones' },
{ id: 2, name: 'Smart Watch', image: '/images/smartwatch.jpg', slug: 'smart-watch' },
{ id: 3, name: 'Bluetooth Speaker', image: '/images/speaker.jpg', slug: 'bluetooth-speaker' },
])

// Log the 404 error to your analytics service
console.log(`404 error occurred at: ${router.asPath}`)
}, [router.asPath])

return (
<div className={styles.container}>
<div className={styles.errorContainer}>
<h1>Oops! Page Not Found</h1>
<p>We can't seem to find the page you're looking for.</p>

<div className={styles.searchContainer}>
<p>Try searching for something else:</p>
<form onSubmit={(e) => {
e.preventDefault()
const query = e.target.search.value
router.push(`/search?q=${encodeURIComponent(query)}`)
}}>
<input
type="text"
name="search"
placeholder="Search products..."
className={styles.searchInput}
/>
<button type="submit" className={styles.searchButton}>
Search
</button>
</form>
</div>

<Link href="/" className={styles.homeButton}>
Back to Homepage
</Link>
</div>

<div className={styles.productsSection}>
<h2>You might be interested in:</h2>
<div className={styles.productGrid}>
{featuredProducts.map((product) => (
<Link href={`/products/${product.slug}`} key={product.id} className={styles.productCard}>
<div className={styles.productImageContainer}>
<Image
src={product.image}
alt={product.name}
width={200}
height={200}
className={styles.productImage}
/>
</div>
<h3>{product.name}</h3>
</Link>
))}
</div>
</div>
</div>
)
}

Tracking 404 Errors

It's a good practice to track when users encounter 404 pages so you can fix broken links or create redirects. You can use Google Analytics or other analytics tools to track 404 errors:

jsx
import { useEffect } from 'react'
import { useRouter } from 'next/router'

export default function Custom404() {
const router = useRouter()

useEffect(() => {
// Send event to Google Analytics or your analytics service
if (typeof window !== 'undefined' && window.gtag) {
window.gtag('event', '404', {
'event_category': 'error',
'event_label': router.asPath,
'non_interaction': true
})
}
}, [router.asPath])

return (
// Your 404 page content
)
}

Best Practices for 404 Pages

  1. Keep it simple and friendly: Use clear language and a friendly tone.
  2. Maintain brand consistency: Use your site's design language and color scheme.
  3. Provide navigation options: Include links to important sections of your site.
  4. Add a search functionality: Help users find what they were looking for.
  5. Make it helpful: Suggest alternatives or popular content.
  6. Track 404 occurrences: Monitor which URLs are causing 404s to fix issues.
  7. Responsive design: Ensure your 404 page works well on all devices.

Testing Your 404 Page

To test your custom 404 page, simply try to navigate to a URL that doesn't exist in your application. For example, if you're running your Next.js app locally, go to http://localhost:3000/this-page-does-not-exist.

Summary

Creating a custom 404 page in Next.js is straightforward and can significantly improve user experience when visitors encounter missing pages. By simply adding a 404.js file (for Pages Router) or a not-found.js file (for App Router), you can create a branded error page that guides users back to your functioning content.

Remember to:

  • Keep your 404 page consistent with your overall site design
  • Provide helpful navigation options
  • Consider adding search functionality
  • Track 404 occurrences to improve your site

A well-designed 404 page turns a potential frustration point into an opportunity to help your users and showcase your attention to detail.

Additional Resources

Exercises

  1. Create a custom 404 page for a portfolio website that includes a list of your featured projects.
  2. Implement a 404 page with an animated illustration that reacts to user interaction.
  3. Build a 404 page that keeps track of the URL that caused the error and suggests the closest matching valid URL on your site.
  4. Design a 404 page that integrates with a backend API to suggest content based on the missing URL path.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)