Is there a way to allow not-found pages to exist in nested dirs?
Answered
Multiply posted this in #help-forum
MultiplyOP
Currently I can only make not-found work by placing it directly in
/app but our system is localiced under /app/[locale] and placing it there, or in any other nested folder for nested layouts to work, triggers the default not found error page.Answered by Multiply
Wrapping up the original issue:
The fix was to add a catch-all route at the same level or deeper than the defined
The catch-all route should return notFound() and it'll select the nearest
The
The fix was to add a catch-all route at the same level or deeper than the defined
not-found.tsx page.The catch-all route should return notFound() and it'll select the nearest
not-found.tsx.The
not-found.tsx page is unfortunately not SSR rendered for me when testing the solution, so it's not perfect, but got me further.70 Replies
Plott Hound
unfortuantely not! as far as i know
MultiplyOP
I guess I'll try to rewrite /not-found to a localized path 

Plott Hound
i'd love to be able to put it in a top level route group like this:
/app
/app/(my-cool-layout)/not-found.tsx
/app
/app/(my-cool-layout)/not-found.tsx
but it just doesnt work
MultiplyOP
Alternatively I'll have Fastly cache a localized page, and serve that content when it sees a 404 status code, but next.js isn't happy about that usually.
Yes, me too!
Plott Hound
my solution was to import my layout things into the not-found and make it look like the rest of the site
but its not ideal
MultiplyOP
Wouldn't that cause rerenders and rehydration anew? 👀
Plott Hound
not the layout file sorry just my UI
i have my auth wrapper in (my-cool-layout) so i have no access to auth in not-found which sucks
MultiplyOP
I've just split my UI up in parallel routes for caching purposes, so it'll be a pain for 404's to reimplement all that. 😦
Plott Hound
yeah it will. i'd recommend just making a simple 404 design for now and pray something changes in the future 

MultiplyOP
We've been holding off on the pages -> app migration since "stable" announcement, and we are still hitting roadblocks.
I can't even get the old 404 page to work anymore, after having both app and pages side-by-side 😦
I can't even get the old 404 page to work anymore, after having both app and pages side-by-side 😦
Plott Hound
let me get back to you in an hour after i've done some experimenting
MultiplyOP
I think last resort will be handling it in the CDN if I can't make rewrites work. I assume /not-found won't be going through middlewares?
Plott Hound
is it the fact you need custom 404 pages depending on the routes?
MultiplyOP
I just need them localized.
Plott Hound
ah i see
MultiplyOP
/app/[locale]/not-found.tsxPlott Hound
let me get back to you, i just work up and im sure coffee will help
MultiplyOP
Or even better
/app/[locale]/(default)/not-found.tsx so I can have my layouts addedPlott Hound
did you read this? https://github.com/vercel/next.js/discussions/50518
MultiplyOP
I'll try using
[...locale] but I worry it might match too much.Plott Hound
yeah see how you get on. im going to do some testing now.
its not ideal but it should work for localisation at least 🤞
MultiplyOP
I think my problem is mostly matching on non-existing routes.
But it might go away when I add a catch all route?
Plott Hound
yeah it should
which lib are you using for i18n?
as some of them have baked in support for not-found and localisation
MultiplyOP
None. We're rolling our own for now, since we want to decrease our overall bundlesize.
We used to have next-i18next rolling, but we're never changing locale directly on the page, so it's major overkill.
We used to have next-i18next rolling, but we're never changing locale directly on the page, so it's major overkill.
I mean, we're still using that for our pages route, but we're actively moving away from it.
So I can confirm, adding a catch-all that does notFound indeed selects the nearest not-found.tsx
app/[locale]/(default)/[...slug]/page.tsxSelects
app/[locale]/(default)/not-found.tsx@Multiply So I can confirm, adding a catch-all that does notFound indeed selects the nearest not-found.tsx
Plott Hound
ok thats good news.
MultiplyOP
But I probably wouldn't suggest using
[...locale] unless I'm missing something.I don't know if you can have multiple catch all segments, and if yes, how greedy they are.
Plott Hound
no i think that would be bad practice and bad dx
i'll keep looking for solutions
but at least this sort of works for now
MultiplyOP
I think it makes sense you need to call notFound manually, but the default not-found ideally should look for the best matching not-found.tsx.
It's probably going to be difficult to do, as you can have multiple folders with each their own not-found.tsx
It's probably going to be difficult to do, as you can have multiple folders with each their own not-found.tsx
I am noticing something funky though. It seems that the layout is flashing in on 404's, but not any other normal page.
I am unsure if this is a dev-mode thing or not, but the DOM only consists of scripts with
__next_f.push for error pages.It's the same for production builds.
Plott Hound
i just tested it and im getting the same. its a white flash that is very noticable
MultiplyOP
Especially if main-app-*.js is slow to load on slower connections.
Plott Hound
ok i added a loading.tsx to the root and it handles it
not getting the flash anymore
MultiplyOP
app/loading.tsx or app/[locale]/(default)/loading.tsx?Plott Hound
app/loading.tsx i tested it without the catch all so its for root level navigationi'll try it for the route group
MultiplyOP
I'm not sure I understand how
loading.tsx solves it, but I'm keen to see your folder structure. 😄I see the same thing, that loading in my catch all solves it.
But that'll cause all my catch-all's to have a loading state, which is undesirable.
I might be able to force static?
Plott Hound
ok say i have this structure:
/about/page.tsx
/not-found.tsx
and i try to navigate from /about to /madeup i get a big white flash while it loads and it looks bad.
if i add
/loading.tsx
and do the same it gracefully shows the loading page and i dont get the white flash
/about/page.tsx
/not-found.tsx
and i try to navigate from /about to /madeup i get a big white flash while it loads and it looks bad.
if i add
/loading.tsx
and do the same it gracefully shows the loading page and i dont get the white flash
MultiplyOP
I see the same thing as you, but you still get a flash of content.
Since we're using full page caching in our CDN, having it cache the loading state seems bad.
MultiplyOP
Iterating a bit on this again, I've tried to use
dynamic = 'force-static, and also generateStaticParams, but the not-found.tsx under app/[locale]/(default) is not prerendered, or even mentioned by the build process.https://github.com/vercel/next.js/issues/62228 I'll tag along in this one, I suppose.
Plott Hound
yeah i've spent an hour digging around and it seems to be a bug
follow the issue and pray i guess
MultiplyOP
I've been praying for so long already. 🥹
@Multiply I've been praying for so long already. 🥹
Plott Hound
wish i had better news, im in the same boat with various issues
MultiplyOP
I've tried commenting on the issue, but getting feedback from the vercel team has been tough. They also have a bunch of open issues, so I don't blame them, but it's really frustrating, because we really want to be able to use the app directory.
MultiplyOP
Wrapping up the original issue:
The fix was to add a catch-all route at the same level or deeper than the defined
The catch-all route should return notFound() and it'll select the nearest
The
The fix was to add a catch-all route at the same level or deeper than the defined
not-found.tsx page.The catch-all route should return notFound() and it'll select the nearest
not-found.tsx.The
not-found.tsx page is unfortunately not SSR rendered for me when testing the solution, so it's not perfect, but got me further.Answer
MultiplyOP
It just occurred to me that when we add loading.tsx the not-found.tsx does not give status code 404, but 200. 🕹ï¸
Plott Hound
404 for non-streamed responses