Multi-tenancy
Multi-tenancy
Serve multiple Makeswift sites from a single Next.js application by mapping tenants to Site API keys.
Multi-tenancy lets you run one Next.js codebase that serves content for many independent Makeswift sites. Each tenant gets its own content, pages, and branding while sharing the same set of registered components and a single deployment.
Routing approaches
Choose the routing approach that fits your use case:
Route tenants with subdomains like siteA.example.com
Route tenants with URL path prefixes like example.com/siteA
Both approaches share the common configuration described on this page. The routing-specific middleware is covered in each sub-guide.
The Visual Builder requires a subdomain-based host URL to connect to each site, because a Makeswift host URL is an origin only and cannot contain a path. Both routing approaches use subdomain host URLs for the builder.
Prerequisites
Before setting up multi-tenancy, make sure you have:
- An existing Next.js App Router project with Makeswift installed. If you don’t have one, follow the App Router installation guide.
- Two or more Makeswift sites in your workspace, each with its own Site API key.
Set up environment variables
Install @t3-oss/env-nextjs for type-safe environment validation:
Create an env.ts file at the root of your project. Each tenant needs a subdomain identifier and a Site API key. The ROOT_DOMAIN variable identifies the root domain the app is served from, used to distinguish tenant subdomains from the bare root domain.
Add the values to .env.local:
Set ROOT_DOMAIN to localhost during development. In production, set it to your real domain (for example, example.com).
Create the tenant mapping
Create a tenants.ts file in lib/makeswift/ that maps subdomain identifiers to Site API keys and exposes helpers for resolving a tenant from a host.
Key functions:
getApiKeyreturns the Site API key for a tenant and throws if the tenant is unknown.isValidTenantIdchecks whether a subdomain is a known tenant.getSubdomainFromHostextracts the subdomain from a host header relative toROOT_DOMAIN.getTenantFromHostresolves a host to a known tenant, falling back todefaultfor the root domain or any unrecognized host.
Update the catch-all page route
Replace your existing catch-all route with one that extracts the tenant from the first path segment and creates a tenant-specific Makeswift client.
The middleware (configured in each sub-guide) rewrites the URL so the first path segment is always the tenant identifier. The remaining segments form the Makeswift page path used to fetch the correct snapshot.
Update the Makeswift API handler
The API handler enables Draft Mode and the Visual Builder. It is excluded from middleware, so it resolves the tenant from the host header directly via getTenantFromHost.
Because the builder always connects via a subdomain host URL, getTenantFromHost resolves the correct tenant from that subdomain. For the root domain or unknown hosts, it falls back to the default tenant.
Update the root layout
Add a new tenant
Adding a tenant requires environment variables plus a small wiring change in two files:
Next steps
Follow one of the routing-specific guides to configure the middleware for your approach:
- Subdomain-based routing — tenants identified by subdomain (
siteA.example.com) - Path-based routing — tenants identified by URL path prefix (
example.com/siteA)