I'm encountering a "404 Not Found" error when trying to refresh a dynamic page in my Next.js application deployed on DirectAdmin. The error occurs only when I attempt to refresh the page, but navigating to it from a different route works fine.
Here are the details of my setup:
When I land on a dynamic page, let's say /products/123, everything works as expected. However, if I refresh the page or directly access the URL /products/123, I receive the following error:
Not Found The requested URL was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
I suspect there might be an issue with the routing configuration in DirectAdmin, but I'm not sure how to resolve it. I've checked my Next.js pages and routing setup, and everything seems to be in order.
I tested it on other types of servers and it worked well, but I think there is a problem with Directadmin!
Here's my code:
pages/index.jsx
import Link from 'next/link'
import { useEffect, useState } from 'react'
export default function HomePage() {
const [todos, setTodos] = useState([]);
useEffect(() => {
async function fetchData() {
const res = await fetch('https://jsonplaceholder.typicode.com/todos?_sort=id&_order=ascs&_limit=5');
const data = await res.json();
setTodos(data);
}
fetchData();
}, []);
return (
{todos && (
<div>
<h1>Todos</h1>
{
todos.map(todo => (
<Link
href={`/todo/${todo.id}`}
className="block p-2"
>
{todo.title}
</Link>
))}
</div>
)}
)
}
pages/todo/[slug].jsx
import { useRouter } from 'next/router';
import { useState, useEffect } from 'react';
export default function Todo() {
const router = useRouter();
const { id } = router.query;
const [todo, setTodo] = useState(null);
useEffect(() => {
async function fetchTodo() {
const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);
const data = await res.json();
setTodo(data);
}
if (id) {
fetchTodo();
}
}, [id]);
if (!todo) {
return <div>Loading...</div>;
}
return (
<div>
<p>{todo.id}</p>
<h1>{todo.title}</h1>
</div>
);
}
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
trailingSlash: true,
}
module.exports = nextConfig
The reason for this is because of next export.
Next export builds static HTML files. If you look at your output folder you probably see something like this.
This is what the browser sees. So since there is no HTML file is in the static output that matches /todo/1.html it produces a 404.
When the server gets a request for /todo/1 you want to serve the user /todo/[slug]/index.html.
Rewrite are normal pretty easy to set up
If you turn off next export it will work as you expect