Photo by Miguel Orós on Unsplash
[#2 - Hashnode clone] Vercel's Platforms Starter Kit notes.
Into the wild.
Okey, so today I decided to play around with the Vercel Platforms Starter Kit and it is awesome. No words. Standing ovation to Vercel for the products they are building with great developer experience. I'm still going through the code but it is very readable and very precise. Also Next.js is such a great framework for you to fast develop applications with less code than usual.
Folder structure
As we all know, Next.js routing is based on its filesystem. The platforms
template adds up a couple of interesting folders to this file structure. We are used to the regular Next.js file structrure:
pages
|
|-- api/
|-- hello.ts
|-- _app.tsx
|-- index.tsx
The platforms
template adds up three more folders inside of pages
:
app
folderhome
folder_sites
folder
pages
└───api
└───app
│ │ -- index.tsx
│ │ -- login.tsx
│ │ -- settings.tsx
│ │
│ └───post
│ │ │ -- ...
│ │
│ └───site
│ │ -- ...
│
└───home
│ │ -- index.tsx
│
└───_sites
│ │
│ | -- [site]
│ │ │ -- index.tsx
│ │ │ -- [slug].tsx
Three important folders
The
app
folder holds theapp.example.com
subdomain. The one that the Vercel team thought as an admin panel. You can create your account, login and manage your settings from this subdomain. Theapp
folder structure in this example containsposts
andsites
as folders as well, meaning that from this subdomain a user can create sites and posts to be displayed on those sites.The
_sites
folder holds the sites information for each user. For example:amilcar.example.com
,camila.example.com
. If you see, eachsite
has anindex.tsx
that acts as its homepage, and a[slug]
that in this example renders thepost
you can create in theapp.example.com
subdomain.The
home
folder would be the folder that holds up our main domainexample.com
.
Changing the app
subdomain name
To change the app
folder name for something more meaningful like account
for example, what you would have to do is to, first of all of course, rename the folder. Then open the _middleware.ts
file and verify if the currentHost
is account
instead of app
.
const currentHost =
process.env.NODE_ENV === 'production' && process.env.VERCEL === '1'
?
hostname
.replace(`.vercel.app`, '')
: hostname.replace(`.localhost:3000`, '')
if (currentHost == 'account') {
url.pathname = `/account${pathname}`
return NextResponse.rewrite(url)
}
Don't forget to replace http://app.localhost:3000
to http://account.localhost:3000
everywhere you set it as a default argument, like in .env for example.
The middleware
is in charge of redirect
or rewrite
to the Response object. In this case we are concerned about the hostname that comes in the request headers. That hostname is the subdomain at what the user is pointing to. And depending on that we would like to redirect or rewrite
Difference between redirect and rewrite
A redirect rule instructs the client (usually a browser) to switch URLs and navigate to the destination of the rule. Redirect rules are typically used for old paths that you’d like to redirect to new ones.
In contrast, a rewrite rule does not change the original URL; it simply serves the content of the rule destination at the original path. The browser cannot tell that the content was served from a different path or URL, making it possible to display content from a different path or URL on any other path on your site.
render.com: Redirects and Rewrites
Basically, on a redirect the server will tell the browser 'hey, you need to go to this URL instead'. And then the browser will change URL's. And will make another request to the server for that new URL.
The rewrite takes place in the server. A browser makes a request and gets served, period. But the server decides what resource will be serve, the browser is completely unaware of the process so it remain the same URL.
This is what allow us to serve data to multiple subdomains, either defined by us for specific parts of our application, or dynamic subdomains for our users to interact.
if (!pathname.includes('.') && !pathname.startsWith('/api')) {
if (currentHost == 'account') {
if (
pathname === '/login' &&
(req.cookies['next-auth.session-token'] ||
req.cookies['__Secure-next-auth.session-token'])
) {
url.pathname = '/'
return NextResponse.redirect(url)
}
url.pathname = `/account${pathname}`
return NextResponse.rewrite(url)
}
if (
hostname === 'localhost:3000' ||
) {
url.pathname = `/home${pathname}`
return NextResponse.rewrite(url)
}
url.pathname = `/_sites/${currentHost}${pathname}`
return NextResponse.rewrite(url)
}
The snippet above will handle all possible scenarios for when a request comes in.
If
currentHost
isaccount
, check if pathname is/login
, if there's a session redirects to/
because user is already logged in, otherwise he can go to the desired page within theaccount
subdomain.When the hostname is 'localhost:3000' it rewrites to
/home
meaning, the user can stay inlocalhost:3000
and will be served with files within thehome
directory in our folder structure.If there's none of those two options then the server will serve from
_sites
folder. Meaning dynamic subdomains.
So this, in a top-level way, is how Hashnode is handling multiple subdomains on its platform. Vercel also gives you the ability to set up custom domains via its API. But that's gonna be another blog post, because I don't know how that works and gotta get into it. So until next time, folks!