How tenancy works (Next.js on Vercel)
// middleware.ts: resolve tenant from host
const host = req.headers.get("host") // nova.fanhub.app
const tenant = await tenants.byHost(host) // edge cache
req.headers.set("x-tenant-id", tenant.id)
return NextResponse.rewrite(
new URL(`/t/${tenant.slug}${pathname}`, req.url))
-- Postgres row level security
create policy tenant_isolation on members
using (tenant_id = current_setting('app.tenant')::uuid);
Custom domains via Vercel Domains API, one theme JSON per tenant, integrations as per-tenant OAuth tokens in an encrypted table, webhooks fan out through a queue.