Skip to content

How to Build a Multi-Tenant App with Custom Domains Using Next.js

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:

The code for this app can be found here. You can also deploy this template to Vercel.


At the end of this tutorial, you'll get a powerful full-stack application with the following features:

  1. Multi-tenancy – programmatically assign unlimited custom domains, subdomains, and SSL certificates to your users
  2. Ultra-performant blog posts cached via Vercel's Edge Network, with the ability to invalidate the cache on-demand (when users make changes) using Incremental Static Regeneration.
  3. AI powered Markdown editor for a Notion-style writing experience
  4. Drag & drop / copy & paste image uploads
  5. Custom fonts, 404 pages, favicons, sitemaps for each site
  6. Dynamic Open Graph images for each blog post
CleanShot 2023-07-05 at 08.39.10.png
CleanShot 2023-07-05 at 08.39.02.png

1. Set up your Next.js project

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 platforms

This will create a new folder in your current directory called platforms. Note that you might run into dependency tree resolving issues during this step, but you can safely ignore it.

Once this step is complete, navigate into the folder and launch the app with pnpm:

cd platforms && pnpm i && pnpm dev

The new application has the following structure:


Aside from the /api folder, there are 3 main folders in the /app directory:

These folders contain the basic app structure for a multi-tenant app and leverages the latest Next.js App Router features like Server Actions, revalidateTag, dynamic OG images, etc.

2. Set up environment variables

To run this app, we'll need to set up the required environment variables.

To do that, convert the .env.example file that’s located at the root of the repo into a .env file.

Here are the set up instructions for each of the environment variables:

  1. NEXT_PUBLIC_ROOT_DOMAIN: This is the domain of your app (e.g.,, etc.)
  2. POSTGRES_PRISMA_URL, POSTGRES_URL_NON_POOLING: Follow the steps here to provision a Vercel Postgres instance. If you have already deployed the template, you can pull the env vars with the Vercel CLI by running vc env pull (full docs here).
  3. BLOB_READ_WRITE_TOKEN: Follow the steps here to provision a Vercel Blob instance. If you have already deployed the template, you can pull the env vars with the Vercel CLI by running vc env pull.
  4. NEXTAUTH_SECRET, AUTH_GITHUB_ID & AUTH_GITHUB_SECRET: These are the secrets required for GitHub OAuth and login via NextAuth.js. You can generate them here (caveat: the generator uses AUTH_SECRET instead of NEXTAUTH_SECRET, you'll have to change that accordingly).
  5. AUTH_BEARER_TOKEN: This is your Vercel authentication token that can be found here.
  6. PROJECT_ID_VERCEL: This is your Vercel Project ID that can be found in your Vercel Project settings page (<org>/<project>/settings). Since you haven't deployed your project to Vercel yet, you can leave this blank for now but remember to come back to add this after you've completed Step 5.
  7. TEAM_ID_VERCEL: This is your Vercel Team ID that can be found in your Vercel Team settings page (<org>/settings)
  8. OPENAI_API_KEY: Required for AI text generation in the text editor. Get one here.
Note: When developing locally, don't forget to add the NEXTAUTH_URL environment variable in your .env file and set the value to http://app.localhost:3000. You won't need to do this in production since NextAuth automatically detects the URL from your Vercel environment.

3. Publish your Prisma Schema

The template comes pre-populated with the necessary Prisma schema for this app. All you need to do to publish this schema to your database is run the following command:

npx prisma db push

Note: If you have already cloned and deployed the template, you can skip this step, since the build script automatically runs prisma db push for you.

4. Update your NextAuth.js callback URLs

In step 2, we set up a GitHub app using the GitHub Client Generator.

However, we still need to customize the callback URLs for the GitHub App in order for the OAuth process to work properly

First, go to Developer Settings on GitHub and click on the GitHub app that you created earlier. Then, under the "Identifying and authorizing users" section, add the following 2 callback URLs:

  1. http://app.localhost:3000/api/auth/callback/github
  2. https://app.<YOURDOMAIN.COM>/api/auth/callback/github
    CleanShot 2023-06-29 at 21.25.13.png

Save your changes, and you're all set! You can now go back to the app login page and log in with GitHub.

CleanShot 2023-06-29 at 21.31.33.png

5. Deploy to Vercel

Finally, we’ll be deploying the repo to Vercel.

1. First, create a new Github repository and push your local changes.

2. Deploy it to Vercel. Ensure you add all environment variables that you configured earlier to Vercel during the import process.

3. In your Vercel project, add your root domain & wildcard domain.

  • When adding your custom domain, ignore the recommended step to "add the www. version of your domain and redirect your root domain to it" – just add the root domain.
  • To set up wildcard domains, you'll need to add the domain using the Nameservers method (as opposed to the recommended A records method).

That's it – you can now go to app.<YOURDOMAIN.COM>, log in, and start creating some sites!

Bonus: Pageviews Analytics

You might notice that the analytics section of each site is filled with dummy data (with beautiful charts powered by Tremor):

CleanShot 2023-06-29 at 22.04.05.png

We highly recommend using a service like Tinybird to ingest, store, and visualize pageview data for each of your sites. In fact, they have an open-source starter kit that shows how you can set this up in less than 5 minutes – we highly recommend trying it out!


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!

If you run into any issues or have any questions about this guide, feel free to raise them on GitHub or drop them in the Next.js Discord.

Couldn't find the guide you need?