Next.js Discord

Discord Forum

2 applications in 1 project(with route groups) served on 2 domains on vercel

Answered
Broad-snouted Caiman posted this in #help-forum
Open in Discord
Avatar
Broad-snouted CaimanOP
I have question for the nextjs and vercel gurus ..

Is it possible for me to deploy a sub directory of an app to vercel(with a custom sub domain e.g form.example.com) while still having the rest of the same application on the main domain(e.g example.com)?

I need to build 2 applications that are kinda related but I don’t want to have to spin up 2 separate nextjs projects to do so, and I need both hosted / served on different domains
Answered by Broad-snouted Caiman
I have added a condition and seems to work now, but will still test around to make sure

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;
  console.log("pathname", pathname);

  if (pathname.startsWith("/_next")) {
    return NextResponse.rewrite(
      new URL(`http://localhost:3000/${pathname}`, request.url)
    );
  } else {
    return NextResponse.rewrite(
      new URL(`http://localhost:3000/payment-link/${pathname}`, request.url)
    );
  }
}
View full answer

41 Replies

Avatar
joulev
Reproducing my answer in general:

Yes, that’s a multi tenant app.

You have the forms at example.com/forms/:path for example, then rewrite from form.example.com/:path to example.com/:path
Avatar
Broad-snouted CaimanOP
Could you please explain the last part? ie the rewrite path
Avatar
Broad-snouted CaimanOP
here’s what I’m kinda cunning for;

app/(main)/…

app/(form)/[id]

I need pretty much the rest of the application ie things inside (main) to run on the main domain eg example.com and example-app.vercel.app

Then the (form) part would then just run on a sub domain like form.example.com such that when a request comes in like form.example.com/randomuniqueID it can map to app/(form)/[id].tsx
How can I accomplish this?
Avatar
joulev
so i assume you have set up (or know how to set up) the /forms/:path routes

then you have two choices:

1. deploy to a wildcard domain (*.example.com), then you can [check for the hostname of the request](https://github.com/vercel/platforms/blob/29e20e790eaf17d4d5051c23a69636dce724c174/middleware.ts#L21-L23), then [rewrite/redirect to the subpath accordingly if the subdomain is form](https://github.com/vercel/platforms/blob/29e20e790eaf17d4d5051c23a69636dce724c174/middleware.ts#L71-L72) using middleware

this requires you to deploy to a deployment hosting platform supporting wildcard domains though. vercel is one of them, but many services don't support hosting webapps to wildcard domains

2. deploy a separate app to form.example.com that perform the rewrite. that app can be a tiny nextjs app with the rewrite rule handled in next.config.js, but can be written in a separate framework too. this only works if you have a limited number of subdomains, so things like [username].example.com won't work, but form.example.com will work
yes so rename (form) to form so all pages in form.example.com live under a subpath /form
then do this
and rewrite requests to form.example.com to example.com/form
Avatar
Broad-snouted CaimanOP
Wouldn’t this rewrite change the url?
Oh never mind, rewrites don’t change the url
Alright, thanks
Avatar
joulev
no thats a redirect. [rewrites dont change the url](https://nextjs.org/docs/app/api-reference/next-config-js/rewrites)(
yes
Avatar
Broad-snouted CaimanOP
If I have further questions or need some more insights can I contact you here or in dm?
Avatar
joulev
ping me here
Avatar
Broad-snouted CaimanOP
Ok then
Avatar
Broad-snouted CaimanOP
@joulev

Hey, got on update on my lil problem

So I spun up another nextjs app, in that app, added the following rewrite to the config

async rewrites() {
    return [
      {
        source: "/:path*",
        destination: "http://localhost:3000/form/:path*",
      },
    ];
  },


I started this second app in dev mode on port 4000, while I have my main app running on 3000

The main app have the following file structure;
app
(main)
[id]
form
[id]

The rewrite works, how ever I noticed that styles don’t apply when I run the app from the form app(ie where the rewrite is)
This is what page looks like on the main app

url: localhost:3000/form/:something
Image
This is what it looks like on the rewrite side

localhost:4000/:something
Image
No styles seem to be applied
Avatar
joulev
Correct yep, you need to handle static bundle files separately:

If the pathname starts with /_next (indicating a bundled file), rewrite without the subpath (like /payment-link). Else add the subpath to the rewrite
I think you might need middleware for this, the rewrites() in the config file might not be versatile enough
Avatar
Broad-snouted CaimanOP
Could u give an example of what I could add to middleware?
Avatar
joulev
So firstly can you rewrite this to a middleware?
This one
Avatar
Broad-snouted CaimanOP
I have created a middleware.ts file in the rewrite application and added the following code

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;

  return NextResponse.rewrite(
    new URL(`http://localhost${pathname}`, request.url)
  );
}

// See "Matching Paths" below to learn more
export const config = {
  matcher: "/:path*",
};


ran the app again, and got a 404 error
oh wait
i have updated the code

return NextResponse.rewrite(
    new URL(`http://localhost:3000/${pathname}`, request.url)
  );


still did'nt work
I know I’m probably doing something wrong but not sure what it is
@joulev
Avatar
Broad-snouted CaimanOP
Got it to work… thanks 🙂
Avatar
joulev
Oh you got it working? Glad to know, sorry for not being able to help with specific code yet because I’ve been away from my laptop all day
Avatar
Broad-snouted CaimanOP
Actuality it didn’t work exactly as intended

Still getting no styles if I rewrite to

http://localhost:3000/payment-link/${pathname}

but if I rewrite to
http://localhost:3000/${pathname}


styles work, and thats the wrong place to rewrite to
Avatar
Broad-snouted CaimanOP
I have added a condition and seems to work now, but will still test around to make sure

export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;
  console.log("pathname", pathname);

  if (pathname.startsWith("/_next")) {
    return NextResponse.rewrite(
      new URL(`http://localhost:3000/${pathname}`, request.url)
    );
  } else {
    return NextResponse.rewrite(
      new URL(`http://localhost:3000/payment-link/${pathname}`, request.url)
    );
  }
}
Answer
Avatar
joulev
yes it looks good to me. that should work yes
pathname already starts with / so you might want to use http://localhost:3000${pathname} and http://localhost:3000/payment-link${pathname} instead
(ping)
Avatar
Broad-snouted CaimanOP
Oh; ok got it
Avatar
joulev
btw (obviously) don't forget to change localhost:3000 to your actual domain when deploying. you probably want to check for process.env.NODE_ENV here
Avatar
Broad-snouted CaimanOP
Yea already did that too… I just introduced a new env variable called BASEHOST, and then I use that in place of hardcoding localhost
That way when we deploy on vercel we can also just add the vercel application domain there and it should just work
Avatar
West African Lion
Could you help me on my question ? about middleware ?