Communitygithub.com

divinevideo/divine-web

Renderiza um componente de página diretamente na raiz do subdomínio (/) sem redirecionamento de URL em SPAs React Router.

O que é divine-web?

Esta skill resolve o problema comum em aplicações React SPA com roteamento baseado em subdomínio (como `username.exemplo.com`), onde o conteúdo deve ser exibido diretamente na raiz (`/`) sem redirecionar para uma URL como `/profile/id`. Ela elimina a necessidade de redirecionamentos que alteram a URL e prejudicam a experiência limpa de subdomínio, além de evitar páginas em branco quando o componente depende de `useParams()` e não há parâmetros de rota na raiz. A solução envolve três partes: (1) configurar o roteador React para renderizar diretamente o componente de perfil na rota `/` em vez de usar `<Navigate>`, (2) modificar o componente para usar dados injetados globalmente (via `window.__DIVINE_USER__`) como fallback quando `useParams()` não retorna nada, e (3) utilizar um edge worker (Fastly Compute, Cloudflare Workers, etc.) para injetar os dados do usuário no HTML antes da hidratação da SPA. A skill é útil para qualquer desenvolvedor que queira criar sites pessoais com URLs limpas (ex.: `usuario.dominio.com/`), sem comprometer a funcionalidade de rotas normais como `/profile/:npub`. Ela é compatível com React Router v6, edge workers modernos e pode ser facilmente adaptada para diferentes provedores de edge computing.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/divinevideo/divine-web/tree/HEAD/.agents/skills/spa-subdomain-root-render

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

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

  1. Visite usuario.dominio.com/ - a URL deve permanecer em /, sem redirecionamento
  2. O conteúdo do perfil deve carregar corretamente
  3. Verifique no console do navegador se não há erros sobre identificadores ausentes
  4. 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()?.npub como 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/:npub continuem funcionando
  • Considere SEO: o edge worker também deve definir as meta tags apropriadas
  • Links no subdomínio podem usar o componente SmartLink para permanecerem locais para conteúdo do proprietário, mas direcionar para o domínio principal para conteúdo de outros usuários

Referências

Habilidades Relacionadas