Tenants and domains
Subdomain routing, custom domains, and how the platform picks the right tenant per request.
Every store has a tenant slug — a short, URL-safe identifier like
acme or bistro. The slug determines which data the request sees.
Subdomains
By default, each tenant gets a subdomain of the platform domain:
acme.shop.example→ tenantacmebistro.shop.example→ tenantbistro
The middleware reads the Host header, strips the platform domain
suffix, and writes the leading subdomain into the x-tenant header.
Custom domains
A tenant can point its own domain (e.g. acmeshop.com) at the platform.
DNS to NShop, configure the custom domain in the tenant settings, and
the platform resolves the domain to the tenant the same way as
subdomains.
Local development
localhost doesn't have subdomains by default. NShop's middleware
falls back to a tenant cookie if the subdomain can't be parsed, and
falls back further to NEXT_PUBLIC_DEFAULT_TENANT. To work with real
subdomains locally, add 127.0.0.1 acme.localhost bistro.localhost to
your hosts file.
Country and currency
Each tenant has a home country (ISO-2, e.g. NL, IN) and a
currency (EUR or INR), chosen when the tenant is created.
Because Stripe ties a connected account's settlement currency to its
country, these two must agree — INR with country IN, EUR with an
EU country. See Payments → Currency for the full
rules and how to switch an existing store.
Why no environment variable per tenant
Tenants are data, not deployments. Adding a new tenant is a Firestore
write — /tenants/{slug} — not a redeploy. The same Cloud Run service
and the same Cloud Functions serve every tenant.