Next.js Discord

Discord Forum

Multiple Domain Redirection

Answered
BakaPresident posted this in #help-forum
Open in Discord
Hi there, would i be able to do multiple domain redirection in NextJS.

For example, my main site is example.com, can i set it up so that i can handle like

abc.com
xyz.com

Assuming that abc.com and xyz.com has setup their CName record pointing to my example.com.

I was also planning to use Caddy server as it seems that they have the API access which makes it easy when people add domain.

I'm trying to do a link shortener with custom domain
Answered by B33fb0n3
To solve your issue: (see attached)
Either remove the link or keep it and save the id (red line) inside your DB. Then create a folder called [id] or similar. Then fetch the entry from your DB and check if it's exists. If exists, redirect (or rewrite) to it else, call not found.

You can find a quick example of this here: https://codesandbox.io/p/github/xavieroyj/marketable-fyi/csb-n3xdg9/draft/green-grass

--- Edit: Explanation
https://nextjs-forum.com/post/1310029099435298886#message-1324042812144095242
View full answer

80 Replies

@Barbary Lion Yes
Trying to find out a brief direction on where to look at to implement it
I don't get it. I know how to do it for one domain. I'm jus confused about setup for multiple domain in the same project. How does that single NextJS project handle all the different domain.
in my case it's from cloudflare so these are my nameservers
Then do i need to do anything regarding the NextJS app.
Like how does it know that

example.xyz/ABC is supposed to redirect to google.com
I need to setup the redirection logic somewhere right even if it redirects to my main domain
@BakaPresident Like how does it know that example.xyz/ABC is supposed to redirect to google.com I need to setup the redirection logic somewhere right even if it redirects to my main domain
Barbary Lion
import { redirect } from 'next/navigation';

export default function Page() {
  redirect('https://www.google.com');
}
If it's to your own domain you can set it up with nameservers otherwise this is your best bet
@Barbary Lion js import { redirect } from 'next/navigation'; export default function Page() { redirect('https://www.google.com'); }
Ahh alright i'll give it a try. I don't need to even manage any type of next.config or something? Seems wild that i can immediately do that
Barbary Lion
Nope, should theoretically work if I’m understanding your question correctly.
Okayy i'll give it a try! Thanks!

I believe i need https://vercel.com/docs/edge-network/redirects#edge-middleware other than the vercel one becus they only support up to 50 domains iirc
@BakaPresident Okayy i'll give it a try! Thanks! I believe i need https://vercel.com/docs/edge-network/redirects#edge-middleware other than the vercel one becus they only support up to 50 domains iirc
the easiest thing you can do when redirecting mulitple domains to other locations is to use a middleware in my opinion.

You get the host like this:
  // Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
  let hostname = req.headers
    .get("host")!
    .replace(".localhost:3000", `.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`);

And can then do redirections with it. For that I suggest an object that tells which route where to go:
const domainRedirects = {
  'example.xyz': {
    '/ABC': 'https://google.com', // Redirect example.xyz/ABC to google.com
    '/other': '/internal-page' // Redirect example.xyz/other to your internal /internal-page
  },
  'anotherdomain.com': {
    '/': '/' // Redirect root of anotherdomain.com to your app's root
  },
// ... more
};

And then you only need to redirect:
const redirect = domainRedirects[hostname]?.[pathname];

if (redirect) {
  return NextResponse.redirect(new URL(redirect, request.url));
}
@B33fb0n3 the easiest thing you can do when redirecting mulitple domains to other locations is to use a middleware in my opinion. You get the host like this: tsx // Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000) let hostname = req.headers .get("host")! .replace(".localhost:3000", `.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`); And can then do redirections with it. For that I suggest an object that tells which route where to go: tsx const domainRedirects = { 'example.xyz': { '/ABC': 'https://google.com', // Redirect example.xyz/ABC to google.com '/other': '/internal-page' // Redirect example.xyz/other to your internal /internal-page }, 'anotherdomain.com': { '/': '/' // Redirect root of anotherdomain.com to your app's root }, // ... more }; And then you only need to redirect: tsx const redirect = domainRedirects[hostname]?.[pathname]; if (redirect) { return NextResponse.redirect(new URL(redirect, request.url)); }
This one sounds good. I remember the Next.JS middleware being pretty restrictive right.

Because it's possibly a big and dynamic list. Like i need to get to the tablebase in order to match my item.

Like for example,
localhost:3000/abc this will lead to say google.com
my-custom-domain/abc this will make me find the domain which is my-custom-domain in my database table and then match the slug(abc) in order to find the link i'm supposed to redirect it to.

Those domain will be verified that the DNS (CName record) will be added in their DNS records. (I have done that, just hasn't gotten the caddy server to work yet, very hard to know how to test that) so that my middleware can catch them
Is my train of thoughts still correct?
@BakaPresident This one sounds good. I remember the Next.JS middleware being pretty restrictive right. Because it's possibly a big and dynamic list. Like i need to get to the tablebase in order to match my item. Like for example, `localhost:3000/abc` this will lead to say `google.com` `my-custom-domain/abc` this will make me find the domain which is `my-custom-domain` in my database table and then match the slug(abc) in order to find the link i'm supposed to redirect it to. Those domain will be verified that the DNS (CName record) will be added in their DNS records. (I have done that, just hasn't gotten the caddy server to work yet, very hard to know how to test that) so that my middleware can catch them
in my opinion using the middleware is the correct approach as you might have limits inside your DNS configuration.

You are right, the middleware run in edge and because of that some functionalities are not available. However: your data is inside a database and normal fetch functions working fine inside a middleware. So it's even better, because you don't need to do everything manually. You just fetch your "redirectionMap" inside your middleware and the middleware will redirect to the correct place πŸ‘
@BakaPresident solved?
Hi sorry i think so. Haven't got it to try was busy with school
Will test it out this week
alr, looking forward to your resposne
@BakaPresident Will test it out this week
ping me, when you done it inside this thread. I will leave this thread for now
Tropical Kingbird
Latency is 63ms. API Latency is 80ms
@B33fb0n3 ping me, when you done it inside this thread. I will leave this thread for now
Sorry HAHAHAH i'm aware it's been a month. The work got to me...
I've tried deploying it on vercel (It's slow because i think it's in a different region?)
For some reason, it works on my local environment but not on the deployed)
Can verify that the domain is saved into the database.
And it seems that right now, even if i'm using like [slug] without the domain it doesn't work.

e.g. marketable-fyi.vercel.app/test
I think probably because i'm not in the root domain
@BakaPresident Click to see attachment
I haven't read thought the whole thread again, but at least your DNS config is wrong. You need to point to the cname from vercel instead of directly to your project. Point it like this: (see attached).

Green arrow points to the server from vercel and my "www." points also to the name servers of vercel
Wait hold up.

When i visit the vercel link that is provided,
https://marketable-fyi.vercel.app/


I don't land in my landing page anymore. Instead, i land at
Middleware triggered: {
  hostname: 'marketable-fyi.vercel.app',
  path: '/',
  url: 'https://marketable-fyi.vercel.app/'
}
Rewriting to: https://marketable-fyi.vercel.app/marketable-fyi.vercel.app/
@B33fb0n3 yea, lets start by the routing and that begins with your DNS configuration. So please do this: https://discord.com/channels/752553802359505017/1310029099435298886/1323577675264163850
Happy new year btw! Wishing happiness to your family! Thanks for helping πŸ™πŸΌ

Alright so this is my first step.

Firstly, i setup it on my main domain which is marketable.fyi so that it's the main link. (E.g. marketable.fyi will land me at the landing page by right)
2) As my domain requires to know where the main domain belongs to, https://github.com/xavieroyj/marketable-fyi/blob/435a9a1039757b04a9a500de05541db2e93d9ab6/middleware.ts#L40

I'll setup the env variable to point to
@BakaPresident 2) As my domain requires to know where the main domain belongs to, https://github.com/xavieroyj/marketable-fyi/blob/435a9a1039757b04a9a500de05541db2e93d9ab6/middleware.ts#L40 I'll setup the env variable to point to
yes, as it's a public variables it should be also pushed to github and like that you don't need to add it to vercel yourself.
Do you see your page now when you visit your domain?
@BakaPresident yes it works!
Great. Now lets go on. In individual key points such as:
- abc
- cdf
- awodo kwdo

What does not work until now?
Alright the entire dashboard works, upon creating basic slugs.

I get 404 when i go to that link. Middleware says
Middleware triggered: {
  hostname: 'www.marketable.fyi',
  path: '/nhfimEn',
  url: 'https://www.marketable.fyi/nhfimEn'
}
So i think it probably could be that i didn't write the middleware logic robust enough?
@B33fb0n3 the image is from your DB?
yup i console log the middleware so it appears in the vercel logs too
alr got it. Where inside your middleware (or page) is the request to your DB (to see if it matched somewhere)?
@BakaPresident https://github.com/xavieroyj/marketable-fyi/blob/main/app/%5Bdomain%5D/%5Bslug%5D/route.ts
Great, now we pushing forward to your solution... πŸ‘
First we check if we getting there from the middleware:
Add a console.log inside your route.ts on the very top. Do you see the console.log when you visit a link?
Alright rerunning the deploying >_> The server and the local environment development is so different :C
Okay i see hello world
Which means it gets route here
@BakaPresident nope it doesn't get hit
alr, instead of having this as a route, change it to an page:
https://github.com/xavieroyj/marketable-fyi/blob/357fee61820a7245119985dc377fbb630dd4f956/app/%5Bdomain%5D/%5Bslug%5D/route.ts#L9

So rename to page.tsx.
Add the page syntax:
export default function Page({
  params,
  searchParams,
}: {
  params: { slug: string }
  searchParams: { [key: string]: string | string[] | undefined }
}) {
  // your code here

  return <h1>My Page</h1>
}

The params can be the same.

Do you see the console.log now?
nope still don't see it
@BakaPresident nope still don't see it
it looks like you didn't pushed it yet, did you?
yeah i rechecked i did
@BakaPresident yeah i rechecked i did
Ah the github cache wasn't updated yet. Now I see it.

When you visit your page at:
https://yourdomain.com/mydomain.com/my-slug/

Do you see your console.log now?
Also share the log for this: https://github.com/xavieroyj/marketable-fyi/blob/main/middleware.ts#L56
For that specific request
This is just the standard nextjs routing right?
@BakaPresident just to get this right:
example.com (https://example.com/) -> shows your langingpage
click.example.com (https://click.example.com/some-slug) -> with some slug that redirect to somewhere else (defined in the database)

click as subdomain is just an example

Is this correct?
Yes.

https://www.marketable.fyi/ => Loading page.
https://www.marketable.fyi/nhfimEn => The one i saved in my database as a slug, is redirected to "Hello world" - /[domain]/page.tsx
https://www.marketable.fyi/nhfimEn

https://www.marketable.fyi/marketable.fyi/nhfimEn => Redirects to /[domain]/[slug]/page.tsx
I think the slug one (2nd option) is purely because i haven't setup the database calls yet
But ideally i should be setting up a separate domain. Let's say
click.crocheted-dreams.com/my-slug and trying the redirect first right
Wouldn't it be easier to directly separate it?
To solve your issue: (see attached)
Either remove the link or keep it and save the id (red line) inside your DB. Then create a folder called [id] or similar. Then fetch the entry from your DB and check if it's exists. If exists, redirect (or rewrite) to it else, call not found.

You can find a quick example of this here: https://codesandbox.io/p/github/xavieroyj/marketable-fyi/csb-n3xdg9/draft/green-grass

--- Edit: Explanation
https://nextjs-forum.com/post/1310029099435298886#message-1324042812144095242
Answer
okay i'll have a look
thanks
πŸ™πŸΌ
btw. it looks like the main issue here is that
/some-slug/

will never match to
[domain]/[slug]

as it's missing at the end (see attached)
happy to help