In this guide, you'll learn how to build a full-stack multi-tenant application by using the Platforms Starter Kit and the following technologies:
If you already have an existing project and only want to see the steps for multi-tenancy, skip ahead to steps 4 and 5. Also, the code for this app can be found here.
We’ll be using the Platforms Starter Kit to kickstart our Next.js project.
First, open up your terminal and navigate and run the following:
npx create-next-app --example https://github.com/vercel/platforms/tree/main platforms
This will create a new folder in your current directory called
platforms. Then, you can navigate into the folder, install the dependencies, and launch the app:
cd platforms && npm i && npm run dev
The new application has the following structure:
pages └───api └───app │ │ index.tsx │ │ login.tsx │ │ settings.tsx │ │ │ └───post │ │ │ ... │ │ │ └───site │ │ ... │ └───home │ │ index.tsx │ └───_sites │ │ │ [site] │ │ │ index.tsx │ │ │ [slug].tsx
Aside from the
/api folder, there are 3 main folders in the
/app: All routes for the app subdomain (
app.example.com), where users can customize their individual content pages.
/home: All routes for the landing page (
/_sites: All routes for all user content pages (e.g.
These folders contain the basic app structure for a multi-tenant app. However, only the
/home route works for now. Let’s continue by adding our database.
Note: Don't forget to convert the
.env.example file that’s located at the root of the repo into a
.env file – it'll come in handy later.
Prerequisite: You need to have the PlanetScale CLI installed
Create a new account with PlanetScale.
Using the PlanetScale CLI, create a new database called
pscale db create platforms
Next, connect to the database branch:
pscale connect platforms main --port 3309
In a different terminal window, use the
db push command to push the schema defined in
npx prisma db push
Now that the initial schema has been added, promote your
main branch to production:
pscale branch promote platforms main
You've just provisioned your database! Now, when you go to app.localhost:3000, you should see the following screen:
To push additional schema changes to your database, follow the instructions from PlanetScale on Prisma Migrations.
Don't forget to get your production MySQL
DATABASE_URL from your Planetscale database – you'll need it for when you deploy your app to Vercel later. You can do that by following this guide. Note that your
DATABASE_URL should be in the following format:
Now, let’s add authentication to allow users to create accounts, add new sites, and add custom domains.
We will use the
next-auth library for authentication. This example is preconfigured to use GitHub OAuth. All user data is stored in your PlanetScale database, based on the Prisma schema defined.
To set up GitHub for authentication:
Go to Developer Settings on GitHub.
Click on "New GitHub App".
Name your GitHub App. In our example, we'll call it "Platforms Starter Kit (dev)".
Add your homepage URL (or a placeholder, if you don't have a website yet).
For the "Callback URL" field, put
http://app.localhost:3000. Since GitHub only allows one callback URL per app, we have to create separate apps for
localhost and production (hence the "dev" name in step 3).
If the "Active" field under "Webhook" is checked, uncheck it. Now, click on "Create Github App".
Once your app is created, you should see the following screen. Click on "Generate a new client secret":
Copy the client secret you generated and paste it under the
GITHUB_SECRET value in your
Copy the Client ID and paste it under the
GITHUB_ID value in your
You're all set! You can now go back to the app login page and log in with GitHub.
First, navigate to the
_middleware.js file at the root of your
/pages folder. Inside this file, we have set up rewrite rules to map each subdomain/custom domain to their dynamic routes in
You’ll need to replace all instances of
vercel.pub with your own domain to configure rewrites correctly. If you don't have a custom domain, you can add the
.vercel.app domain that your project was assigned and use that as your custom domain.
Next, we’ll be deploying the repo to Vercel. Note that this is not the final step since we’ll still need to configure the feature for adding custom domains in the next step.
.envfile to Vercel during the import process.
SECRETtoken in the
.envfile and add that as an Environment Variable.
DATABASE_URLyou retrieved in step 2 as an Environment Variable.
www.version of your domain and redirect your root domain to it" – just add the root domain.
We’ll use the Vercel API to add custom domains to your project and assign it to the user's account:
AUTH_BEARER_TOKENfrom your Vercel Accounts Settings page under Tokens. Add that value to your
.envfile under the
VERCEL_PROJECT_IDfor your project from
https://vercel.com/<TEAM_OR_USER_NAME>/<PROJECT_SLUG>/settings. It should be in the format
VERCEL_TEAM_ID– this can be found at
/api/add-domain: Add domains to your Vercel project using this endpoint whenever a user adds it on your platform. This returns 3 possible outcomes:
403: The domain is already owned by another team but you can still request delegation from the team and add it.
409: The domain is already being used by a different project. You can’t add it unless the domain is removed from the project.
200: The domain is successfully added.
/api/check-domain: Checks if a domain has been successfully configured for your project. Returns two possible values:
true: domain has been configured successfully
false: domain has not been configured correctly
/api/request-delegation: If a domain is owned by another team, you can use this endpoint to request delegation from the team and add it. Caveat: we are actively working on improving our domain delegation process and it’s likely that there won’t be the need for this endpoint in the future
/api/remove-domain: Removes domains from your Vercel project using this endpoint whenever a user removes it from your platform.
/api/add-domain endpoint only adds the root domain. If you want to add the
www. subdomain and redirect it to the root, you'll have to perform an additional API call.
Here are some supplementary code snippets that might be required to build Platforms on Vercel:
Avoid [Cumulative Layout Shift](</docs/concepts/analytics/web-vitals#cumulative-layout-shift-(cls)) (CLS) from the native Twitter embed by using our static tweets implementation (supports image, video, gif, poll, retweets, quote retweets, and more).
You'll need a Twitter auth bearer token, which you'll paste into the
TWITTER_AUTH_TOKEN field in your
.env file. Here's how you can get a Twitter auth bearer token.
You'll need a Cloudinary cloud account (
cloudName) and a Cloudinary upload preset (
uploadPreset). Here's how you can get those variables set up.
In this guide, you learned how to build a full-stack multi-tenant application by using the Platforms Starter Kit. From blogging platforms to low-code tools, this starter kit can be a starter kit for a number of different types of applications, we’re excited to see what you build!