Renderização na Raiz do Subdomínio SPA Sem Redirecionamento
Problema
Ao construir roteamento baseado em subdomínio (ex.: usuario.exemplo.com), usar o <Navigate to="/profile/usuario" replace /> do React Router altera a URL, o que anula o propósito de ter uma URL de subdomínio limpa. Além disso, o componente alvo pode exibir uma página em branco se ele depende de useParams() para obter parâmetros de rota que não existem em /.
Contexto / Condições de Ativação
- A página de perfil do subdomínio redireciona para
/profile/npub1...em vez de servir o conteúdo em/ - A página aparece em branco (nenhum conteúdo carrega) na raiz do subdomínio
- O componente usa
useParams()e falha quando renderizado em uma rota sem esses parâmetros - O edge worker injeta dados do usuário em
window.__SUBDOMAIN_USER__ou global similar - Deseja-se que
usuario.dominio.com/seja renderizado como um site pessoal
Solução
1. Roteador: Renderizar Componente Diretamente em Vez de Redirecionar
Antes (causa redirecionamento + alteração de URL):
<Route path="/" element={
subdomainUser
? <Navigate to={`/profile/${subdomainUser.npub}`} replace />
: <Index />
} />
Depois (renderiza em / sem alterar a URL):
<Route path="/" element={
subdomainUser
? <ProfilePage />
: <Index />
} />
2. Componente: Adicionar Fonte de Dados de Fallback
O componente deve verificar os dados de subdomínio injetados quando os parâmetros de rota estiverem faltando.
Antes (apenas verifica parâmetros de rota):
export function ProfilePage() {
const { npub } = useParams<{ npub?: string }>();
const identifier = npub;
if (!identifier) {
return <Error message="Nenhum identificador de usuário fornecido" />;
}
// ... resto do componente
}
Depois (usa dados injetados como fallback):
import { getSubdomainUser } from '@/hooks/useSubdomainUser';
export function ProfilePage() {
const { npub } = useParams<{ npub?: string }>();
const subdomainUser = getSubdomainUser();
// Parâmetro de rota tem prioridade, dados do subdomínio são fallback
const identifier = npub || subdomainUser?.npub;
if (!identifier) {
return <Error message="Nenhum identificador de usuário fornecido" />;
}
// ... resto do componente
}
3. Edge Worker: Injetar Dados do Usuário no HTML
O edge worker (Fastly Compute, Cloudflare Workers, etc.) deve injetar os dados do usuário:
// No edge worker que lida com o subdomínio
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. Acesso aos Dados no Lado do Cliente
// useSubdomainUser.ts
interface SubdomainUser {
subdomain: string;
pubkey: string;
npub: string;
username?: string;
displayName?: string;
// ... outros campos
}
export function getSubdomainUser(): SubdomainUser | null {
if (typeof window === 'undefined') return null;
return (window as any).__DIVINE_USER__ || null;
}
Verificação
- Visite
usuario.dominio.com/- a URL deve permanecer em/, sem redirecionamento - O conteúdo do perfil deve carregar corretamente
- Verifique no console do navegador se não há erros sobre identificadores ausentes
- Confirme que
window.__DIVINE_USER__contém os dados esperados no DevTools
Exemplo
Para divine-web:
ocomedianriley.divine.video/renderiza ProfilePage em/- ProfilePage verifica
useParams()primeiro (vazio em/) - Usa
getSubdomainUser()?.npubcomo fallback a partir dos dados injetados - O perfil carrega sem alteração de URL
Notas
- Este padrão requer coordenação entre o edge worker e o código cliente
- O edge worker deve injetar os dados antes da hidratação da SPA
- Sempre verifique os parâmetros de rota primeiro para que rotas normais como
/profile/:npubcontinuem funcionando - Considere SEO: o edge worker também deve definir as meta tags apropriadas
- Links no subdomínio podem usar o componente
SmartLinkpara permanecerem locais para conteúdo do proprietário, mas direcionar para o domínio principal para conteúdo de outros usuários
Referências
- Rotas React Router v6: https://reactrouter.com/en/main/route/route
- Fastly Compute@Edge: https://developer.fastly.com/learning/compute/