Renderizado en la Raíz del Subdominio SPA Sin Redirección
Problema
Al construir enrutamiento basado en subdominios (ej., usuario.ejemplo.com), usar <Navigate to="/perfil/usuario" replace /> de React Router cambia la URL, lo que va en contra del propósito de tener una URL limpia en el subdominio. Además, el componente destino puede mostrar una página en blanco si depende de useParams() para obtener parámetros de ruta que no existen en /.
Contexto / Condiciones de Activación
- La página de perfil del subdominio redirige a
/perfil/npub1...en lugar de servir contenido en/ - La página aparece en blanco (sin contenido cargado) en la raíz del subdominio
- El componente usa
useParams()y falla cuando se renderiza en una ruta sin esos parámetros - El edge worker inyecta datos de usuario en
window.__SUBDOMAIN_USER__o un global similar - Se desea que
usuario.dominio.com/renderice como un sitio web personal
Solución
1. Enrutador: Renderizar el Componente Directamente en Lugar de Navegar
Antes (causa redirección + cambio de URL):
<Route path="/" element={
subdomainUser
? <Navigate to={`/profile/${subdomainUser.npub}`} replace />
: <Index />
} />
Después (renderiza en / sin cambio de URL):
<Route path="/" element={
subdomainUser
? <ProfilePage />
: <Index />
} />
2. Componente: Agregar Fuente de Datos de Respaldo
El componente debe verificar los datos inyectados del subdominio cuando faltan parámetros de ruta.
Antes (solo verifica parámetros de ruta):
export function ProfilePage() {
const { npub } = useParams<{ npub?: string }>();
const identifier = npub;
if (!identifier) {
return <Error message="No se proporcionó identificador de usuario" />;
}
// ... resto del componente
}
Después (usa datos inyectados como respaldo):
import { getSubdomainUser } from '@/hooks/useSubdomainUser';
export function ProfilePage() {
const { npub } = useParams<{ npub?: string }>();
const subdomainUser = getSubdomainUser();
// El parámetro de ruta tiene prioridad, los datos del subdominio son el respaldo
const identifier = npub || subdomainUser?.npub;
if (!identifier) {
return <Error message="No se proporcionó identificador de usuario" />;
}
// ... resto del componente
}
3. Edge Worker: Inyectar Datos de Usuario en HTML
El edge worker (Fastly Compute, Cloudflare Workers, etc.) debe inyectar los datos del usuario:
// En el edge worker manejando el subdominio
const userData = await fetchUserData(username);
const html = await fetchSpaHtml();
const injectedHtml = html.replace(
'</head>',
`<script>window.__DIVINE_USER__ = ${JSON.stringify(userData)};</script></head>`
);
return new Response(injectedHtml, { headers: { 'content-type': 'text/html' } });
4. Acceso a Datos del Lado del Cliente
// useSubdomainUser.ts
interface SubdomainUser {
subdomain: string;
pubkey: string;
npub: string;
username?: string;
displayName?: string;
// ... otros campos
}
export function getSubdomainUser(): SubdomainUser | null {
if (typeof window === 'undefined') return null;
return (window as any).__DIVINE_USER__ || null;
}
Verificación
- Visita
usuario.dominio.com/- La URL debe permanecer en/, sin redirección - El contenido del perfil debe cargarse correctamente
- Verifica en la consola del navegador que no haya errores sobre identificadores faltantes
- Verifica que
window.__DIVINE_USER__contenga los datos esperados en las herramientas de desarrollo
Ejemplo
Para divine-web:
thecomedianriley.divine.video/renderiza ProfilePage en/- ProfilePage verifica primero
useParams()(vacío en/) - Usa como respaldo
getSubdomainUser()?.npubdesde los datos inyectados - El perfil se carga sin cambio de URL
Notas
- Este patrón requiere coordinación entre el edge worker y el código cliente
- El edge worker debe inyectar los datos antes de la hidratación de la SPA
- Siempre verifica primero los parámetros de ruta para que las rutas normales
/perfil/:npubfuncionen - Considera SEO: el edge worker también debe establecer las metaetiquetas adecuadas
- Los enlaces en el subdominio pueden usar el componente
SmartLinkpara mantenerse locales para el contenido del propietario, pero enlazar al dominio principal para el contenido de otros usuarios
Referencias
- React Router v6 Routes: https://reactrouter.com/en/main/route/route
- Fastly Compute@Edge: https://developer.fastly.com/learning/compute/