The point of choosing Nextjs was for SSR and SEO. We have an external REST API which we query for data on the frontend. But on some pages, we need do a pre-render fetching and display proper 404 Not Found header when API returns 404. This seems to be difficult for me.
The app structure looks like this:
app/p/auth/
├── layout.jsx
├── loading.jsx
├── password-reset
│ └── [key]
│ ├── components
│ │ ├── index.js
│ │ ├── ResetPassword.jsx
│ │ └── SecurityQuestions.jsx
│ ├── page.jsx
│ └── ResolveComponent.jsx
├── reset-successful
│ └── page.jsx
└── sign-up
└── page.jsx
My Problem
A request is being made to http://example.com/p/auth/password-reset/[key] . The key is to be captured and sent to the REST API to validate. If not found, and notFound()
is thrown, it should return a proper 404 HTTP response.
What I have tried
With what I have tried, the only way that works to return a proper 404 header is by throwing notFound()
in app/p/auth/layout.jsx
, but the problem is, the layout is shared amongst other paths (e.g. app/p/auth/sign-up), and I cannot isolate the request in the app/p/auth/layout.jsx
I have tried to isolate the layout.jsx
by deleting the app/p/auth/layout.jsx
and re-creating one in each of the paths, but throwing notFound()
inside app/p/auth/password-reset/[key]/layout.jsx
does not set 404 HTTP header. It returns 200 and further more loads to 404 page.
notFound()
sets 404 header when called in app/p/auth/layout.jsx
but when isolating the layout to sub-folder like app/p/auth/password-reset/[key]/layout.jsx
, it doesn’t set 404 header but it loads 404 page with 200 header. What is the proper way to handle this?
2
Answers
A solution mentioned here is to set the status code explicitly, by doing:
Your middleware would look something like:
make sure you have
app/not-found.tsx
which handlesnotFound()
, non-existing routes and/404
few solutions I came up while encountering this issue:
middleware.ts
file,return NextResponse.rewrite(new URL('/404', req.url))
redirect('/404')
app/layout.tsx
, child components are wrapped in<Suspense>
– if yes, remove global Suspense