Skip to content

Crescimento/Convite: link da sala não gera preview — robots.txt bloqueia o unfurl de /room/ e o card herda a OG genérica da home (robots.ts:13, room/[id]/page.tsx:9-14) #118

Description

@caioross

Contexto

O convite de sala é o loop de aquisição nº1 do CodeRacer: sem login, a única forma de alguém chegar
ao produto por indicação é receber um /room/<code> de um amigo. A frota já construiu as duas pontas
do gesto — copyLink() em src/components/Lobby.tsx:60-65 e o chip "copiar link" em
src/components/RoomView.tsx:265-269 — e a chegada é ótima (o NameGate em
src/components/RoomView.tsx:178-215 já diz "você foi convidado", mostra o código e pré-preenche o
nick do localStorage). O elo fraco é o meio do caminho: como esse link aparece no chat.

Dois defeitos independentes, ambos conferidos na produção (2026-08-01):

1. O robots.txt bloqueia o próprio unfurl. src/app/robots.ts:13 publica Disallow: /room/.
Vários unfurlers respeitam robots.txt antes de buscar a página (Slackbot e Twitterbot são os casos
documentados; Discord e WhatsApp normalmente não). O comentário em src/app/robots.ts:4-6 justifica o
bloqueio por indexação — mas indexação já está impedida pelo robots: { index: false, follow: false }
de src/app/room/[id]/page.tsx:12, que é o mecanismo certo para isso. O Disallow não acrescenta
proteção de índice e custa o preview do convite nos clientes que o respeitam.

2. Quando o unfurl acontece, o card não fala da sala. A rota define title/description próprios
(src/app/room/[id]/page.tsx:9-14) mas nenhum openGraph, então herda a imagem genérica da home.
O convite vira mais um card institucional do CodeRacer em vez de "sala ABC123, entra aí".

Ordem sugerida: puxar depois da #117. Enquanto a origem pública estiver errada, o og:image
aponta para um host 503 e nenhum card renderiza — o efeito desta issue não seria observável.
Não é bloqueio de código: os diffs não se sobrepõem.

Escopo

  • src/app/robots.ts — parar de bloquear o fetch de /room/, mantendo as salas fora do índice pela
    meta noindex que já existe na rota. Atualizar o comentário para registrar a distinção entre
    "não indexar" e "não deixar buscar". /harness/ continua bloqueado.
  • Imagem OG por sala, derivada exclusivamente do código presente na URL — sem nenhuma leitura de
    banco: código em destaque, marca, e uma chamada curta ("entre na corrida"). Espelhar o shape de
    src/app/opengraph-image.tsx em vez de inventar um novo.
  • openGraph/twitter na metadata da rota da sala, para o card usar o título específico que ela já
    monta (Sala <CODE> — entre na corrida) em vez do título do layout raiz.

Restrição de segurança (deliberada): a imagem não pode consultar rooms nem qualquer estado —
nada de "3 jogadores esperando", nome do líder ou linguagem. Um endpoint público que devolve estado de
sala a partir do código seria um vetor de enumeração novo, exatamente o problema que a #103 (policy
using(true), sala privada enumerável) está tratando, e um alvo de abuso sem custo como o da #104
(POST /api/rooms sem rate limit). Tudo que a imagem mostra já é conhecido por quem tem o link.

Acceptance criteria (verificáveis)

  • GET /robots.txt em produção não contém Disallow: /room/; /harness/ segue bloqueado.
  • GET /room/<code> continua servindo <meta name="robots" content="noindex, nofollow"> (ou
    equivalente) — a mudança do robots.txt não pode tornar salas indexáveis. Cole o HTML no PR.
  • GET /room/<code> publica og:image próprio (não o da home) e og:title com o código da sala.
  • A imagem OG da sala responde 200 image/png com 1200×630 e mostra o código pedido; dois códigos
    diferentes produzem imagens diferentes. Cole as duas URLs/screenshots no PR.
  • A geração da imagem não faz nenhuma chamada a Supabase nem lê rooms — verificável por leitura do
    diff; declare isso explicitamente no PR.
  • Código inválido/estranho na URL não quebra a rota nem injeta conteúdo arbitrário na imagem —
    aplique o mesmo saneamento que a rota já usa (params.id.toUpperCase().slice(0, 6),
    src/app/room/[id]/page.tsx:8).
  • Gate: pnpm typecheck · pnpm build · pnpm test verdes.

Dica de abordagem

opengraph-image.tsx é uma convenção de arquivo do App Router e funciona dentro de app/room/[id]/,
recebendo os mesmos params da página — é por aí, sem rota de API nova. Reaproveite as cores de
src/lib/site.ts (themeColor, accentColor) para o card ficar coerente com o da home. Sobre o
robots.txt: a mudança é de uma linha, mas escreva no PR por que noindex na rota já cobre a
preocupação original de src/app/robots.ts:4-6 — é o ponto que um revisor vai querer ver defendido.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Prioridade normalarea:infraCI/CD, build, tooling, deploy, depsarea:uiInterface, design system, animação, game feel

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions