Appearance
Hosts and routing
One frontend build serves several kinds of host. src/lib/hosts.ts decides what the current host is for:
| Host | Role | Serves |
|---|---|---|
app.qurtuba.in | app | Sign-in and every dashboard |
qurtuba.in, www.qurtuba.in | marketing | The platform's own public pages |
docs.qurtuba.in | docs | The documentation (a separate project) |
<label>.qurtuba.in | site | An entity's public site, found by label |
| any other host | site | An entity's public site, found by custom domain |
localhost, *.vercel.app previews | combined | Everything, as before the split |
The split is off until VITE_APP_HOST is set. Until then the root domain keeps serving dashboards too, so the code can ship before app. exists. With it on:
- on the marketing host, sign-in and dashboard paths redirect to
app.<root>with the same path; app.<root>/goes to the signed-in home, or to/login.
Locally, <label>.localhost:8080 stands in for a subdomain. Browsers resolve *.localhost to your machine.
Resolving a site
public.resolve_site_host(p_label, p_hostname) answers "which published site is this?" in one call, for every kind of site:
- a label, for
<label>.<root>, is looked up inapp.site_labels, a view over every entity'ssubdomain; - a hostname, for a custom domain, is looked up in
public.site_domains(statusactive).
It returns kind, entity_id, subdomain and slug. src/public-site/PublicHostSite.tsx calls it and renders the matching module from src/public-site/siteModules.ts.
The edge router
Vercel only takes wildcard domains with Vercel's nameservers, and qurtuba.in is on Cloudflare. So:
| Record / setting | Value |
|---|---|
app CNAME → Vercel | DNS only; a domain on the Vercel project |
* CNAME → Vercel | Proxied, so every label reaches the Worker |
sites CNAME → Vercel | Proxied; the Cloudflare for SaaS fallback origin for custom domains |
Worker route *.qurtuba.in/* | qurtuba-site-router, fail open |
The Worker (infra/cloudflare/site-router) asks resolve_site_host whether the host is a published site, and caches the answer for 5 minutes. If it is, the Worker fetches the page from app.qurtuba.in, and the browser keeps its own address. If it isn't, the request passes through untouched to wherever that name points. So the zone's other proxied records need no list, and a label only the wildcard matches gets a "no site here" page.
Fail open means that once the free plan's daily request limit runs out, traffic goes straight to origin instead of erroring.