Ir al contenido

White-label y branding por organización

CÉNIT permite a cada cliente personalizar colores, logo y slug de su organización. La detección de subdominio (<slug>.cenitams.com) está implementada en modo pasivo: el middleware lo detecta y lo expone via header, pero no enforce ni cambia comportamiento. El white-label “completo” (dominio propio, login skin por slug, cookies cross-subdomain) es fase 2 pendiente.

  • Problema que resuelve: el club no quiere que su staff vea la marca CÉNIT al abrir la app — quiere ver sus colores y logo.
  • Casos típicos: Nacional ve azul/rojo Nacional y escudo del club. Otro cliente puede sobreescribir a sus colores con un par de hex values desde Settings.
  • Planes que lo incluyen: marcada como custom_branding (pro + enterprise en lib/plans.ts). Atención comercial: hoy la feature no está gateada en el código — un cliente esencial puede usarla sin pagar. Issue abierto.
  • Diferenciador vs competencia: la mayoría de las plataformas SaaS de performance vienen con su marca fija. Esto permite vender a clubes que tienen identidad visual fuerte.
Prometible hoyNO prometer todavía
Colores primario y secundarioDominio propio (app.miclub.com)
Logo en la barra lateralLogin con look del club antes de autenticarse
Slug único (miclub.cenitams.com)Cookies que sigan al usuario cross-subdomain

Solo hop y dir pueden editar branding desde /dashboard/settings.

  • Nombre de la orgorganizations.name.
  • Slugorganizations.slug, kebab-case, único, 2–40 chars, validado en DB por CHECK (migration 085).
  • Logoorganizations.logo_url, sube archivo a Supabase Storage.
  • Color primarioorganizations.primary_color (sobreescribe --azul).
  • Color secundarioorganizations.secondary_color (sobreescribe --rojo).

El Shell aplica los colores con <style dangerouslySetInnerHTML> inyectando las CSS custom properties al HTML root. Ver Sistema de temas para el listado completo de variables.

middleware.ts corre detectOrgSubdomain(host) en cada request. La lógica:

  • Hosts ignorados (no son orgs): cenitams.com, www.cenitams.com, cenitapp.com (legacy 302), localhost, IPs.
  • Cualquier otro host con >2 segmentos: parts[0] es candidato a slug.
  • Si el slug matchea el regex kebab-case y mide 2–40 chars, se propaga via header x-org-subdomain al request.

Ningún consumer hoy lee ese header — queda disponible para fases siguientes. Activando NEXT_PUBLIC_SUBDOMAIN_DEBUG=true se loggea en cada request.

Player surface: indirecto. El jugador ve los colores y logo de su club al abrir /player, pero no accede via subdominio propio — usa cenitams.com igual que el staff. Su sesión carga la org y aplica el branding.

  • organizations.slug — único, kebab-case (migration 085 enforce formato).
  • organizations.primary_color, secondary_color — hex strings.
  • organizations.logo_url — URL a Supabase Storage.
  • Multi-tenant — el branding es por organización, igual que los datos.
  • Sistema de temas — define qué CSS custom properties son sobreescribibles.
  • Superadmin — al crear una org, el superadmin setea slug, colores y logo iniciales.

Slug + UI de branding + detección pasiva de subdominio. Todo funciona pero ningún subdomain <slug>.cenitams.com está configurado en Cloudflare DNS hoy.

Para que miclub.cenitams.com realmente funcione:

  1. DNS wildcard *.cenitams.com en Cloudflare.
  2. Custom-domain config en Cloudflare Workers para que el host wildcard llegue al worker.
  3. Cookies cross-subdomain — Supabase auth cookies con domain=.cenitams.com para que la sesión sobreviva entre subdominios.
  4. Login skin por slug — en /login, leer x-org-subdomain y renderizar logo/colores del club antes de que el usuario se autentique.
  5. Enforcement — opcionalmente, redirigir a cenitams.com si el slug del subdominio no matchea la org del usuario logueado.

app.miclub.com con CNAME a cenitams.com + Cloudflare custom domain por cliente. Sin SPEC ni precio definido. Es candidato fuerte a diferenciador Enterprise.

custom_branding está en lib/plans.ts solo para pro/enterprise, pero el formulario de Settings no chequea canUse. Un cliente esencial hoy puede subir logo y cambiar colores sin pagar.