# Design: crescimento SEO e GEO do portfólio **Status:** pronto para execução somente após o hardening técnico **Data:** 2026-09-04 **Pesquisa-base:** `.superpowers/seo-research-2026-09-04.md` **Plano predecessor:** `docs/superpowers/plans/2026-09-04-portfolio-hardening.md` ## Objetivo Melhorar descoberta, compreensão e confiança do portfólio em busca orgânica e experiências generativas sem redesenhar a interface, criar páginas por cidade ou publicar alegações sem prova. A implementação corrige frescor e entidades, torna metadados e Open Graph específicos por rota, conecta serviços a evidências, aprofunda três cases sustentados pelo próprio repositório e por código público, separa os caminhos de contratação e consultoria e documenta medição/operações externas sem alegar que foram executadas. ## Gate de sequência SEO começa **depois** do gate final do hardening. Na data deste design, apenas a Task 1 do hardening estava concluída; as Tasks 2–12 ainda alterariam arquivos compartilhados. O executor deve aceitar como baseline o estado final comprovado pelo predecessor, não restaurar o estado observado durante esta pesquisa. Interfaces finais que este design consome: - `PortfolioProjectView` preserva todo projeto editorial e anexa `demoAvailability`/`demoCheckedAt`. - `app/layout.tsx` é server-first, sem providers globais de scroll/animação, e mantém Header, overlays leves, conteúdo e analytics. - `GoogleAnalytics` usa consentimento opt-in, chave `evandro.analytics-consent.v1`, valores `granted | denied`, endpoint oficial do Google e revogação alcançável. - `package.json` oferece `pnpm lint`, `pnpm typecheck`, `pnpm test`, `pnpm build`; Node 22, pnpm 9.15.9 e Next 16.3.0 ficam fixados pelo ruling de segurança do hardening. - `Footer`, `Contact`, hero command-center, globo, starfield, notebook, tipografia, paleta preto/papel/verde ácido, cartões e tokens `ds-*` permanecem como direção visual invariável. - `data/project-health.json` e o `globals.css` não rastreado da raiz continuam fora deste escopo. Se o gate final do hardening não estiver verde, a execução deste plano não começa. Não se adapta SEO ao código intermediário. ## Princípios e limites ### Sempre - Uma URL canônica por intenção; páginas existentes são enriquecidas em vez de duplicadas. - Conteúdo factual, legível no HTML e apoiado por fonte verificável. - Base em Garuva e atendimento no Norte de Santa Catarina/remoto somente no alcance já declarado pelo site. - `Person` é a entidade prestadora e autora; `WebSite` é o site; `ProfilePage` existe na rota de currículo; cada serviço tem `Service`; rotas não-home têm `BreadcrumbList` quando a trilha existe na interface. - Metadata API e convenções de imagem do Next.js 16; sem pacote novo. - CTAs usam os componentes/classes atuais. A separação é semântica e de destino, não um novo layout. - Privacidade descreve exatamente o comportamento do consentimento entregue pelo hardening. ### Nunca - Página-clone de Garuva, Joinville, Curitiba ou outra cidade. - `llms.txt`, `FAQPage`, `keywords` em metadata, `ProfessionalService`, ou `LocalBusiness` sem negócio/local comprovado. - Coordenada, endereço postal, preço, cliente, review, volume, ranking, resultado comercial ou métrica de performance não comprovados. - Afirmação de que framework, schema ou formatação garante ranking/citação. - Mudança de paleta, tipografia, grid, hero, efeitos preservados, arquitetura de informação ou biblioteca visual. - Dependência, commit, branch ou ação em Search Console/Bing/Cloudflare nesta iniciativa de documentação. ## Arquitetura de conteúdo `lib/site-content.ts` continua sendo a fonte das páginas de serviço e case. Não será criada uma CMS ou segunda camada de dados. A extensão mínima é: ```ts export const intentCtas = { hiring: { label: "Avaliar perfil para contratação", href: "/curriculo", }, consulting: { label: "Solicitar consultoria técnica", href: "/#contact", }, } as const; export type CtaIntent = keyof typeof intentCtas; export interface EvidenceSource { id: string; label: string; url: string; } export interface SourcedStatement { text: string; sourceIds: string[]; } export interface CaseStudyDetail { answer: SourcedStatement; challenge: SourcedStatement; implementation: SourcedStatement[]; boundaries: SourcedStatement[]; sources: EvidenceSource[]; } export interface ServicePageContent { slug: string; navLabel: string; eyebrow: string; seoTitle: string; metaDescription: string; headline: string; answer: string; intro: string; audience: string[]; outcomes: string[]; process: string[]; stack: string[]; ctaIntent: "consulting"; ctaLabel: string; ctaHref: string; relatedCaseIds: string[]; faq?: { question: string; answer: string }[]; } export interface CaseStudyContent { id: string; title: string; subtitle: string; summary: string; impact: string; stack: string[]; demoUrl?: string | null; githubUrl?: string | null; detail?: CaseStudyDetail; } ``` `detail` é opcional porque somente três cases têm evidência suficiente nesta rodada. O conjunto deve ser exatamente `as-servicos`, `nutriscan` e `twins-lab`, sem depender da ordem. Afirmações técnicas/factuais em `answer`, `challenge`, `implementation` e limites comparativos exigem pelo menos um `sourceId` externo. O limite puramente editorial de AS Serviços mantém `sourceIds: []`: não será criada URL fictícia ou circular para uma decisão deste design. Qualquer ID presente deve resolver para uma fonte única dentro do mesmo case, e toda `EvidenceSource.url` deve ser um permalink GitHub `/blob//...`. A página exibe as fontes ao final do conteúdo aprofundado. A relação existente `ServicePageContent.relatedCaseIds` permanece como única fonte de relacionamento. A função nova: ```ts export function getRelatedServices(caseId: string): ServicePageContent[] { return servicePages.filter(({ relatedCaseIds }) => relatedCaseIds.includes(caseId), ); } ``` permite links recíprocos sem manter duas listas divergentes. ### CTAs Os seis serviços mantêm `ctaIntent: "consulting"` e levam a `/#contact`, com rótulo específico de conversa técnica/projeto. As páginas de case mostram dois caminhos usando o sistema visual existente: - **“Avaliar perfil para contratação”** → `/curriculo` (`hiring`); - **“Solicitar consultoria técnica”** → `/#contact` (`consulting`). O currículo mantém o caminho de contratação e oferece um link secundário para `/servicos` a quem procura consultoria. Não há formulário, modal ou estado de URL novo. ## Cases escolhidos e fonte de cada campo ### 1. AS Serviços (`as-servicos`) Foi escolhido por ter demo pública, repositório público atual, README técnico, manifesto e implementação legível da cena. | Campo novo | Texto factual autorizado | Fontes | | --- | --- | --- | | `detail.answer` | “Site institucional em Next.js 16 que representa quatro frentes de engenharia com uma cena Three.js gerada em código: uma casa wireframe e uma placa-mãe ligadas ao progresso da rolagem.” | `README.md`, `package.json`, `lib/three/engine.ts` | | `detail.challenge` | “Representar engenharia física e software na mesma narrativa visual sem depender de um modelo 3D pronto.” | `README.md`, `lib/three/engine.ts` | | `detail.implementation[0]` | “O motor monta casa, instalação elétrica e placa-mãe com geometrias e linhas do Three.js.” | `lib/three/engine.ts` | | `detail.implementation[1]` | “O canvas converte a rolagem em progresso de 0 a 1 e o entrega ao motor da cena.” | `components/scene/scene-canvas.tsx` | | `detail.implementation[2]` | “A qualidade pode cair para `static`, `low`, `medium` ou `high` conforme WebGL, reduced motion, economia de dados, conexão e capacidade do dispositivo.” | `lib/three/engine.ts` | | `detail.boundaries[0]` | “O case demonstra implementação e decisões técnicas; não atribui geração de leads, ranking ou ganho de performance.” | Limite puramente editorial deste design; `sourceIds: []` | Fontes imutáveis de referência: - `https://github.com/evandrodevbr/as-servicos/blob/abeb9946a704139336942bfd41ad163ccfe1e685/README.md` - `https://github.com/evandrodevbr/as-servicos/blob/abeb9946a704139336942bfd41ad163ccfe1e685/package.json` - `https://github.com/evandrodevbr/as-servicos/blob/abeb9946a704139336942bfd41ad163ccfe1e685/lib/three/engine.ts` - `https://github.com/evandrodevbr/as-servicos/blob/abeb9946a704139336942bfd41ad163ccfe1e685/components/scene/scene-canvas.tsx` ### 2. NutriScan (`nutriscan`) Foi escolhido porque o código público confirma fluxos concretos de busca, validação e fallback, embora a documentação e o manifesto discordem sobre versão e persistência. O texto novo usa apenas o cruzamento verificável. | Campo novo | Texto factual autorizado | Fontes | | --- | --- | --- | | `detail.answer` | “Aplicação web para consultar produtos alimentícios por nome ou código de barras, combinando cache JSON com a API Open Food Facts.” | `app/api/search/route.ts`, `app/api/products/[barcode]/route.ts`, `lib/openFoodFactsApi.ts` | | `detail.challenge` | “Reduzir a dependência da API externa e manter um caminho explícito para buscas e consulta por código.” | `app/api/search/route.ts`, `app/api/products/[barcode]/route.ts` | | `detail.implementation[0]` | “A busca consulta o cache primeiro, permite modo somente-cache e recorre ao Open Food Facts quando faltam resultados.” | `app/api/search/route.ts` | | `detail.implementation[1]` | “A consulta por código remove caracteres não numéricos, aceita de 8 a 13 dígitos, consulta cache e usa a API externa como fallback.” | `app/api/products/[barcode]/route.ts` | | `detail.implementation[2]` | “O wrapper cancela requisições após oito segundos e diferencia busca por nome de busca por código.” | `lib/openFoodFactsApi.ts` | | `detail.boundaries[0]` | “A página não afirma PWA, MongoDB, histórico de usuários, disponibilidade, volume de produtos ou resultado de saúde, porque as fontes atuais não sustentam esse conjunto de forma consistente.” | `package.json`, `prisma/schema.prisma`, README e código comparados | Fontes imutáveis de referência: - `https://github.com/evandrodevbr/nutriscan/blob/ef0e6d4eca1f8588bb6981c1cfa58e4b7db1302b/app/api/search/route.ts` - `https://github.com/evandrodevbr/nutriscan/blob/ef0e6d4eca1f8588bb6981c1cfa58e4b7db1302b/app/api/products/%5Bbarcode%5D/route.ts` - `https://github.com/evandrodevbr/nutriscan/blob/ef0e6d4eca1f8588bb6981c1cfa58e4b7db1302b/lib/openFoodFactsApi.ts` - `https://github.com/evandrodevbr/nutriscan/blob/ef0e6d4eca1f8588bb6981c1cfa58e4b7db1302b/package.json` - `https://github.com/evandrodevbr/nutriscan/blob/ef0e6d4eca1f8588bb6981c1cfa58e4b7db1302b/prisma/schema.prisma` - `https://github.com/evandrodevbr/nutriscan/blob/ef0e6d4eca1f8588bb6981c1cfa58e4b7db1302b/README.md` ### 3. Twins Lab (`twins-lab`) Foi escolhido porque o repositório contém um simulador, persistência, autenticação e uma rota de streaming observáveis. As métricas promocionais e recursos marcados como futuros no README são excluídos. | Campo novo | Texto factual autorizado | Fontes | | --- | --- | --- | | `detail.answer` | “Protótipo de gêmeo digital industrial com autenticação, simulador de reator, persistência MongoDB e streaming de eventos do servidor.” | `package.json`, `app/api/reactor/stream/route.ts`, `simulators/reactor/reactor-simulator.ts` | | `detail.challenge` | “Expor estados simulados do reator a uma interface autenticada e manter histórico/status do simulador.” | `app/api/reactor/stream/route.ts`, `simulators/reactor/reactor-simulator.ts` | | `detail.implementation[0]` | “A rota exige sessão do NextAuth antes de abrir o stream.” | `app/api/reactor/stream/route.ts` | | `detail.implementation[1]` | “A resposta usa `text/event-stream`, envia estados/dados/erros em intervalos de dois segundos e limita a conexão a dez minutos.” | `app/api/reactor/stream/route.ts` | | `detail.implementation[2]` | “O simulador salva dados e estado no MongoDB e notifica clientes quando execução ou cenário mudam.” | `simulators/reactor/reactor-simulator.ts` | | `detail.boundaries[0]` | “O case não usa as alegações de economia, ROI, precisão, manutenção preditiva futura, equipamento real, WebSocket, OpenRouter ou atualização sub-segundo.” | README comparado ao código público | Fontes imutáveis de referência: - `https://github.com/evandrodevbr/twins-lab/blob/f83f99a7417f16ece0cd7fe4832ba122e7152d0c/package.json` - `https://github.com/evandrodevbr/twins-lab/blob/f83f99a7417f16ece0cd7fe4832ba122e7152d0c/app/api/reactor/stream/route.ts` - `https://github.com/evandrodevbr/twins-lab/blob/f83f99a7417f16ece0cd7fe4832ba122e7152d0c/simulators/reactor/reactor-simulator.ts` - `https://github.com/evandrodevbr/twins-lab/blob/f83f99a7417f16ece0cd7fe4832ba122e7152d0c/README.md` ## Resposta factual cedo A primeira descrição abaixo do H1 deve responder o que é oferecido ou demonstrado sem slogan genérico: - Serviços usam o novo `answer` antes das listas de público/processo. - Os três cases aprofundados usam `detail.answer.text` no hero; os demais mantêm o `summary` atual, após remoção de afirmações não comprovadas. - Hubs explicam em uma frase o que o usuário encontra e para qual próximo passo cada cartão aponta. - Currículo começa com profissão, base e modalidades já declaradas; não promete disponibilidade, prazo de resposta ou presença física nova. Texto regional comum autorizado: **“Base em Garuva, atendimento a projetos no Norte de Santa Catarina e atuação remota.”** Ele substitui enumerações extensas de cidades onde a página não demonstra presença local. ## Modelo de entidades e dados estruturados IDs canônicos, exportados por `lib/seo.ts`: ```ts export const SEO_IDS = { website: `${siteUrl}/#website`, person: `${siteUrl}/#person`, profilePage: `${siteUrl}/curriculo#profile-page`, } as const; ``` ### Grafo raiz Somente: ```json { "@type": "WebSite", "@id": "https://evandro.dev.br/#website", "url": "https://evandro.dev.br", "name": "Evandro.dev.br", "inLanguage": "pt-BR", "publisher": { "@id": "https://evandro.dev.br/#person" } } ``` ```json { "@type": "Person", "@id": "https://evandro.dev.br/#person", "name": "Evandro Fonseca Junior", "url": "https://evandro.dev.br", "image": "https://evandro.dev.br/edev.jpg", "homeLocation": { "@type": "Place", "name": "Garuva, Santa Catarina, Brasil" }, "sameAs": ["GitHub público", "LinkedIn público"] } ``` Não há endereço postal, coordenada, preço, raio, catálogo de ofertas ou Instagram divergente sem validação. ### Currículo `ProfilePage` aparece somente em `/curriculo`, referencia `SEO_IDS.person`, define `isPartOf` para `SEO_IDS.website` e não inclui `dateModified` até existir uma data editorial persistida. A pessoa pode ser referenciada por `@id`; não é duplicada com propriedades divergentes. ### Serviço Cada `/servicos/[slug]` emite: - `Service` com `@id: ${pageUrl}#service`, `url`, `name`, `description`, `provider: { "@id": SEO_IDS.person }`; - `areaServed` limitado a Garuva e Norte de Santa Catarina, sem coordenada/raio/endereço; - `BreadcrumbList` com `@id: ${pageUrl}#breadcrumb` e posições contíguas 1–3. ### Hubs, cases e privacidade Hubs preservam `CollectionPage`/`ItemList` quando os itens visíveis coincidem com a lista. Cases removem `Article` incompleto; usam `BreadcrumbList`, pois autoria/datas/imagem de artigo não estão comprovadas como publicação editorial. Currículo, hubs, cases, serviços e privacidade têm breadcrumbs visíveis/estruturados coerentes. ## Frescor - `app/sitemap.ts` não inclui `lastModified` enquanto não houver data editorial estável por URL. - `changeFrequency` e `priority` também são removidos: não há fonte operacional que os mantenha e mecanismos os tratam apenas como dicas. - `/curriculo` remove `new Date().toISOString()`. - Nenhuma data muda por build ou request. Critério determinístico: duas chamadas consecutivas de `sitemap()` em instantes diferentes retornam estruturas profundamente iguais. ## Metadata e Open Graph por rota Toda rota indexável tem title, description e canonical próprios. Nenhuma metadata contém `keywords`. Title e description refletem a intenção da rota e não enumeram cidades. Open Graph usa `ImageResponse` e a convenção de arquivo do Next.js, com `1200×630`, `image/png`, alt específico e template visual compartilhado em `lib/og-card.tsx`. O template reutiliza preto, papel e verde ácido e apenas tipografia/texto; não introduz nova direção visual nem asset falso. Arquivos por segmento: - `app/opengraph-image.tsx` — marca/home; - `app/servicos/opengraph-image.tsx` — hub de serviços; - `app/servicos/[slug]/opengraph-image.tsx` — serviço selecionado pelos params; - `app/cases/opengraph-image.tsx` — hub de cases; - `app/cases/[slug]/opengraph-image.tsx` — case selecionado pelos params; - `app/curriculo/opengraph-image.tsx` — perfil profissional; - `app/privacidade/opengraph-image.tsx` — privacidade e consentimento. Metadata dinâmica usa o mesmo conteúdo de `site-content.ts` que a página e a imagem; slug inválido retorna resposta 404 da imagem, sem imagem genérica enganosa. Twitter herda o mesmo card grande. ## Links recíprocos - Cada cartão de case relacionado dentro de um serviço recebe link interno “Ler case: {título}” antes dos links externos de demo/código. - Cada case lista os serviços encontrados por `getRelatedServices(caseId)` com anchors descritivos. - O hub de cases mantém “Ler case”. O hub de serviços mantém “Abrir página”, sem link direto externo. - Demo/GitHub continuam externos, com `rel="noreferrer"` ou `noopener noreferrer`. - Estado de demo continua obedecendo `PortfolioProjectView`; SEO não reintroduz filtragem ou health fetch. ## Privacidade e consentimento Criar `/privacidade` com metadata/canonical/OG próprios e conteúdo factual: 1. responsável e contato: Evandro Fonseca Junior, e-mail já publicado; 2. contato do formulário: os dados digitados são transformados em mensagem e abrem o WhatsApp; o site não possui endpoint próprio de armazenamento desse formulário; 3. analytics: antes de `granted`, nenhuma tag Google é carregada; a escolha fica em `localStorage` sob `evandro.analytics-consent.v1`; publicidade permanece negada; concessão pode criar cookies `_ga*`; revogação desativa novas coletas e expira cookies acessíveis conforme o hardening; 4. links externos: GitHub, LinkedIn, Instagram, demos e WhatsApp seguem políticas próprias; 5. alteração de preferência: usar o controle “Preferências de privacidade” entregue pelo hardening; 6. direitos/contato: solicitações são encaminhadas ao e-mail publicado; 7. data de vigência fixa: 2026-09-04. A página não declara certificação jurídica, retenção que não foi configurada, compartilhamento que não foi verificado ou conformidade automática. O diálogo de consentimento e o Footer passam a ter link crawlable para `/privacidade`, usando estilos atuais. ## Documento operacional externo A implementação cria `docs/seo-geo-operations.md` como runbook declarativo. Cada ação começa desmarcada e inclui evidência esperada, sem texto que sugira execução: - Google Search Console: verificar propriedade, submeter sitemap, inspecionar as 17 URLs finais (as 16 atuais + privacidade), registrar canônica/cobertura e baseline de 90 dias, abrir relatórios de IA quando disponíveis na conta. - Bing Webmaster Tools: verificar/importar propriedade, submeter sitemap, inspecionar URLs e registrar AI Performance; IndexNow fica fora até haver atualização frequente. - Cloudflare: comparar `robots.ts` com resposta pública, Managed Robots, AI Crawl Control e WAF; registrar política separada de busca/citação e treino; conferir `200/403/429` em logs. - Medição: p75 de LCP/INP/CLS por template em CrUX/RUM, consultas/landing/conversão, caminhos case→serviço→contato e citações reportadas pelas plataformas. - Ações que exigem conta, publicação ou painel externo continuam humanas e consequenciais; o plano apenas documenta. ## Matriz de conflitos | Área | Hardening/SEO envolvidos | Conflito | Regra | | --- | --- | --- | --- | | `app/layout.tsx` | Hardening Task 4; SEO entidades | Hardening achata providers sem tocar JSON-LD | SEO relê o arquivo final e altera apenas metadata/JSON-LD após Task 12. | | `app/components/GoogleAnalytics.tsx` | Hardening Task 11; SEO privacidade | Consentimento ainda não existe no baseline atual | SEO consome a chave/estados finais e adiciona somente link/cópia coerente. | | `app/components/Footer.tsx` | Hardening Task 9 ajusta testes; SEO adiciona privacidade | Teste e links podem mudar | Hardening primeiro; SEO preserva o contrato acessível final. | | `lib/portfolio-data.ts`/JSON | Hardening Tasks 2–3; SEO cases | Tipo de projeto/health muda | SEO não altera o loader nem `PortfolioProjectView`; modifica apenas fatos dos três registros JSON. | | `app/cases/[slug]/page.tsx` | SEO conteúdo/schema/metadata | Mesma rota em múltiplas preocupações | Uma única slice de case possui toda a rota; OG fica em arquivo irmão. | | `app/servicos/[slug]/page.tsx` | SEO resposta/schema/links/CTA/metadata | Mesmo arquivo | Uma única slice de serviço possui toda a rota; OG fica em arquivo irmão. | | `lib/site-content.ts` | Conteúdo factual, serviços e cases | Fonte compartilhada | Contrato e valores fecham na primeira tarefa; slices posteriores são somente consumidoras. | | `lib/og-card.tsx` | Todas as imagens OG | Template compartilhado | Criar uma vez; arquivos de segmento só fornecem texto. | | `app/sitemap.ts` | Frescor e nova rota privacidade | Task de entidades remove datas; privacidade adiciona URL | A task de privacidade adiciona a URL ao sitemap já sem datas; reler antes de editar. | ## Critérios observáveis de aceite 1. O gate completo do hardening está verde antes do primeiro arquivo de produção SEO ser alterado. 2. Duas execuções de `sitemap()` produzem a mesma saída e incluem 17 URLs canônicas sem `lastModified` artificial. 3. Nenhum HTML contém `ProfessionalService`, `LocalBusiness`, `FAQPage`, meta `keywords`, coordenada, preço ou endereço postal não comprovado. 4. O grafo raiz tem um `WebSite` e uma `Person`; `/curriculo` tem um `ProfilePage` que referencia a mesma pessoa; serviços têm `Service`; breadcrumbs têm posições contíguas e URLs canônicas. 5. Todas as rotas indexáveis têm title, description, canonical e OG coerentes; cada endpoint de imagem responde `200 image/png` em 1200×630 e alt específico. 6. Serviço → case e case → serviço são links internos reais com nome descritivo. 7. AS Serviços, NutriScan e Twins Lab exibem resposta, desafio, implementação, limites e fontes; nenhuma página atribui resultado comercial. 8. Demais cases não recebem profundidade genérica nem campos vazios. 9. A primeira descrição de cada serviço/case responde factualmente ao propósito da URL. 10. Texto regional usa base em Garuva, Norte de Santa Catarina e atuação remota, sem alegar escritórios ou presença por cidade. 11. CTAs de contratação levam a `/curriculo`; CTAs de consultoria levam a `/#contact`; ambos mantêm o sistema visual atual. 12. `/privacidade` descreve o consentimento final, está linkada pelo diálogo e Footer e não afirma ação/garantia jurídica inexistente. 13. O runbook externo registra ações e evidências esperadas sem marcar nenhuma como feita. 14. Desktop, mobile e reduced motion preservam direção visual, conteúdo, foco e fluxo de consentimento do hardening. 15. Jest focado, Biome, TypeScript, build e smoke em navegador encerram verdes. ## Riscos e mitigação | Risco | Impacto | Mitigação | | --- | --- | --- | | Executar sobre hardening incompleto | Alto | Gate explícito e releitura dos arquivos finais compartilhados. | | Duplicar ou divergir fatos entre JSON e `site-content.ts` | Alto | Atualizar somente os três cases na mesma tarefa e testar frases proibidas/links de fonte. | | Fonte pública mudar | Médio | URLs com SHA fixo; tratar o case como retrato técnico daquela revisão. | | Converter README promocional em fato | Alto | Usar somente código/manifests cruzados; registrar exclusões por case. | | Schema válido sintaticamente, mas semanticamente incorreto | Alto | Grafo mínimo, propriedades visíveis e testes de IDs/referências/breadcrumbs. | | OG aumentar duplicação | Médio | Um componente visual puro e arquivos de segmento mínimos. | | Link de privacidade contradizer consentimento | Alto | Consumir literalmente chave/estados/comportamento final do hardening e testar juntos. | | Texto regional virar doorway | Alto | Nenhuma nova rota de cidade; uma frase factual compartilhada. | | CTA separar só a aparência | Médio | Destinos observáveis distintos: contratação `/curriculo`, consultoria `/#contact`. | | Testes fixarem classes/copy incidental | Médio | Assertar rotas, links, schema, fontes e comportamentos; não classes ou wrappers. | ## Auto-revisão contra as 57 fontes | Grupo do relatório | Quantidade | Como o design incorporou | Conflito evitado | | --- | ---: | --- | --- | | Google [G1–G13] | 13 | Conteúdo útil/original, canônicas, schema visível, sem frescor falso e medição em ferramentas próprias | Sem city-clone, escala artificial, schema especial de IA ou promessa de ranking. | | Bing + Web Vitals [B1–B3, W1] | 4 | Resposta cedo, páginas focadas, evidência, runbook de AI Performance e p75 de campo | Sem IndexNow prematuro ou score de laboratório alegado como resultado. | | Schema.org [S1–S6] | 6 | `Person`, `Service`, `ProfilePage`, `BreadcrumbList` mínimos e conectados | `ProfessionalService`, `LocalBusiness` e `FAQPage` excluídos. | | Next.js [N1–N7] | 7 | Metadata por rota, `generateMetadata`, imagens por segmento e build estático | Sem nonce, pacote experimental ou alteração de CSP/analytics do hardening. | | GEO/crawlers [A1–A2, C1–C4, L1] | 7 | Fontes visíveis e medição tratadas como experimento; política de bots só documentada | Sem `llms.txt`, allowlist executada ou causalidade de citação. | | Mercado observado | 20 | Clareza de intenção, links, projetos e prova de primeira mão | Sem stuffing, endereço, testemunho, métrica ou autoridade inferida de concorrente. | | **Total** | **57** | **Todos os grupos possuem decisão correspondente.** | **Nenhuma recomendação proibida foi reintroduzida.** | A revisão também confirmou: oito slices bastam; não há dependência nova; os três cases têm fonte por campo técnico/factual, com exceção explícita apenas para o limite editorial de AS; ações externas não são executadas; e a direção visual permanece invariável.