How a host becomes a tenant, a language and a mode before the app sees the request.
A tenant app resolves its tenant from the request host, in this order:
acme.kikstart.ai is tenant acme.acmestore.co.za maps to whichever tenant registered it.A {slug}.kikstart.ai host never reaches the lookup. Deployment preview hosts skip it entirely, since a preview alias can never be a customer domain. Hits and misses are both cached, misses for less time, so an unmapped host cannot become an open query.
In development the same rule holds on {slug}.localhost:<port>, which browsers route to the local machine without a hosts-file entry.
Before the app sees the request, a proxy rewrites the path under three internal segments: the tenant, the language and the mode. The rewrite is internal. Browser URLs, links and the pathname the app reads stay free of all three, and the prefix always comes from the resolved host, never from the request path, so typing another tenant's slug into a URL reaches nothing.
| Segment | Carries | Resolved from |
|---|---|---|
| Tenant | Which store | The host, as above. |
| Language | Which language the page renders in | The URL when it names one, else the language cookie, else the browser's preference, narrowed to the languages the platform supports. |
| Mode | The admin's per-request mode, view or edit, and its modifiers | The proxy alone; nothing else writes it. |
Reading a segment does not cost a page its static shell, because the page is already prerendered per value. That is why the tenant gate and the translation layer read segments and never headers or cookies.
API routes, webhooks, the agent endpoint, short links and the metadata files (robots.txt, sitemap.xml, social images) are never rewritten. They resolve the tenant from a request header the proxy sets on every request regardless, since a route handler cannot read a segment.
Registering a customer domain is an operations task that replaces the tenant's set of hostnames. The domain must also be added to the tenant's auth instance as a trusted origin, or sign-in from it is rejected. Routing and auth are separate allowlists.