Subdomain-based routing
Subdomain-based routing
Route tenants using subdomains in a multi-tenant Makeswift application.
Subdomain-based routing uses the subdomain to identify the tenant. For example, siteA.example.com serves Site A and siteB.example.com serves Site B. The bare root domain (example.com) serves the default tenant. Subdomain URLs are also what the Visual Builder requires to connect to a site.
Before following this guide, complete the common configuration steps.
How it works
A request flows through the system in four steps:
- Detect the tenant from the subdomain, resolved against the configured
ROOT_DOMAIN. - Resolve to a Makeswift site by mapping the subdomain to the appropriate Site API key.
- Rewrite the URL so the resolved tenant is the first path segment.
- Serve tenant-specific content from the correct Makeswift site.
Add the middleware
Create a middleware.ts file at the root of your project:
The middleware resolves the tenant from the subdomain and rewrites the URL so the tenant is always the first path segment. The bare root domain and any unrecognized host (for example, www or a platform preview URL) fall back to the default tenant.
Makeswift API routes (/api/makeswift/*) are excluded via config.matcher — the API handler resolves the tenant from the host itself.
Configure the Visual Builder host URLs
Each Makeswift site needs its host URL set to the subdomain URL so the Visual Builder can connect.
In the Makeswift dashboard, open the settings for each site and set the host URL:
For production, replace localhost:3000 with your deployed domain (for example, siteA.example.com).
Test the setup
Start the development server and verify each tenant loads:
Most browsers (Chrome, Firefox, Edge) resolve *.localhost to 127.0.0.1 automatically. Safari does not — see Resolving subdomains on Safari below.
Production deployment
The same logic works in production with two changes:
- Set
ROOT_DOMAINto your real domain (for example,ROOT_DOMAIN=example.com). Tenant subdomains are resolved relative to this value, and the bare apex domain maps to the default tenant. - Point each tenant subdomain at your deployment. Configure wildcard DNS (
*.example.com) or an individual DNS record per tenant sositeA.example.com,siteB.example.com, and so on all reach the same app. Update each Makeswift site’s host URL to its production subdomain.
Resolving subdomains on Safari
Chrome, Firefox, and Edge resolve *.localhost to 127.0.0.1 automatically, but Safari does not. To make the tenant subdomains work in Safari during local development, map them in /etc/hosts:
-
Edit
/etc/hosts: -
Add an entry for each subdomain:
/etc/hosts -
Visit
http://siteA.localhost:3000,http://siteB.localhost:3000, and so on.
Example repository
For a complete working implementation, see the multi-tenant host example repository.