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.62k stars 735 forks source link

Duplicate content on [domain] path for subdomain+customDomain? #302

Closed zevi-wiply closed 1 year ago

zevi-wiply commented 1 year ago

Discussed in https://github.com/vercel/platforms/discussions/300

Originally posted by **zevi-wiply** August 22, 2023 If I'm understanding correctly, the generateStaticParams in [domain]/layout.tsx returns as paths all subdomains and all non-null customDomains, and then the page fetches the site data based on unique subdomain/customDomain, etc..
This would mean though that there are two separate static pages, one on the subdomain path and one of the customDomain path that both fetch the exact same site data. I assume it's implemented this way so that we don't need to do any queries in middleware, but isn't it bad practice and a waste of storage having two different sites displaying the same content or am I missing something here?
Any suggestions as to how I could implement custom subdomains and custom domains without generating two separate static pages with the same content?
steven-tey commented 1 year ago

Hey @zevi-wiply! There are several ways you can avoid/improve this:

  1. Redirect subdomain to custom domain if exists: We actually have a section of the code that lets you do that: https://github.com/vercel/platforms/blob/main/app/%5Bdomain%5D/layout.tsx#L105-L112
  2. Setting a canonical URL that points to the custom domain if it exists: https://github.com/vercel/platforms/blob/main/app/%5Bdomain%5D/layout.tsx#L50-L56
tomgreeEn commented 8 months ago

How about this as a "yes, and", to prevent duplicate paths ever being selected for pre-render:

const allPaths = allSites
    .flatMap(({ subdomain, customDomain }) => [
      subdomain &&
        !customDomain /*   <-----  Only include subdomains where there's no customDomain    */ && {  
          domain: `${subdomain}.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`,
        },
      customDomain && {
        domain: customDomain,
      },
    ])
    .filter(Boolean);