vercel / platforms

A full-stack Next.js app with multi-tenancy and custom domain support. Built with Next.js App Router and the Vercel Domains API.
https://app.vercel.pub
5.71k stars 756 forks source link

Custom 404 #174

Closed tobeycodes closed 1 year ago

tobeycodes commented 1 year ago

We want to be able to show a different 404 and 500 page per site. The site param is not available in getStaticProps and you can't use getServerSideProps in 404 or 500 pages.

We tried creating a 404 page in the _sites/[site] folder adding a catch all redirect in fallback to _sites/[site]/404 but fallback redirects do not run when using blocking. We have to use blocking as we cannot build all pages at build time for all sites.

Our current solution is to load the props we need on the client side with window.location.host but that means we need load a blank page until this has completed since we fetch the site settings which is used to render the header, navigation and menus as each site has different configuration.

Are there any other options for us to be able to use a custom 404/500 per site?

mertcanaltin commented 1 year ago

you can have a look at this https://nextjs.org/docs/advanced-features/custom-error-page @tobeycodes

tobeycodes commented 1 year ago

you can have a look at this https://nextjs.org/docs/advanced-features/custom-error-page @tobeycodes

That link does not cover the issue that I am experiencing.

felipedeboni commented 1 year ago

@tobeycodes had this same issue today. We were able to workaround it without front-end code involved.

What you want to do is check if the page exists on your middleware. If the page does not exist than you rewrite the Next response to /_sites/${currentHost}/404.

Create a new file pages/_sites/[site]/404.tsx. This page is going to be server rendered, so you will need a getServerSideProps. Put all your logic to fetch whatever you need, but before returning your object add the following:

context.res.statusCode = 404;

return { /*...*/ }

This way the page works as any other page and you can control the status code sent.

The only downside of this approach is having it server rendered.

tobeycodes commented 1 year ago

@felipedeboni Thanks for sharing your solution. This would mean that we are fetching the page data twice (once in middleware and once in getStaticProps). We have a lot of routes e.g. /blog/[[...post].js, /recipes/[...id].js, etc. So although your solution is probably possible. It is quite impractical across a lot of page routes.

felipedeboni commented 1 year ago

@tobeycodes yes, you can fetch only the page exists on the middleware instead of returning the whole page content. That way it would be faster.

You can also add a cache layer and retrieve same data for both. Sadly you can't pass props from middleware :(

Anyway, we found it better than rendering on client side.

steven-tey commented 1 year ago

The Platforms Starter Kit now supports custom 404 pages :love-cry: