How to serve and redirect a subfolder in Vercel
This is the blog post I wish I have read months ago, when even Vercel's support couldn't help me. Heres what I wanted to do:
- I have windmillui.com hosted with Vercel. It's a Next.js site.
- I wanted to serve a (actually two, but they are very similar) Create React App from a subfolder like: windmill.com/dashboard-html
Seems simple, but I tried to serve the CRA build inside the Next app, using a subdomain like demo.windmillui.com/dashboard-html and a ton of other stuff. In the end, I've just created two Vercel projects, built them and linked them directly from windmillui.com. The result is this aberration https://windmill-dashboard-react.vercel.app/login
The beautiful solution
The only documentation that exists about this is a one line example here and a discussion on GitHub.
Create a vercel.json
file in your project root. This project should be the one that hosts your projects and possibly is where you have your domain setup.
{
"version": 2,
"rewrites": [
{ "source": "/pomodoro/:asset*", "destination": "https://pomodoro-murex.vercel.app/:asset*" },
{ "source": "/(.*)", "destination": "/" }
]
}
TL;DR; The first source
points everything coming to /pomodoro
to https://pomodoro-murex.vercel.app
; :asset*
can have any name, as long as it is present in both source
and destination
and is between :<here you can put anything>*
. The second source
just routes everything else to the current project's root.
You can read about version
in the docs but long story short, use 2
.
To better understand why I setup my rewrites the way I did, you may find useful to know my project structure (it's pretty simple, don't worry).
This blog is part of my personal website, a Next.js app served like you would expect, with my pages living under pages
. It's deployed to Vercel through the GitHub integration. Now I want to serve other projects, from different repositories, from the same domain but different subfolders. In this case estevanmaito.me/pomodoro.
If you try this:
{ "source": "/pomodoro", "destination": "https://pomodoro-murex.vercel.app/" },
It won't work, because, in my case, the Pomodoro app depends on CSS that is only hosted in https://pomodoro-murex.vercel.app, like /static/main.css
, and with the approach above, it would try to access these static assets from https://estevanmaito.me/pomodoro/static/main.css, which doesn't contain any of that.
To solve that we use this line:
{ "source": "/pomodoro/:asset*", "destination": "https://pomodoro-murex.vercel.app/:asset*" }
It will map everything coming after /pomodoro/
to https://pomodoro-murex.vercel.app/
.
We finish routing everything else to the current root with:
{ "source": "/(.*)", "destination": "/" }
Is this the best solution?
I don't know, but after struggling for some time, this is the working solution.
Let me know if you find it useful or you think it could be improved on Twitter @estevanmaito.