About aeo-geo-bestpractices
A Portuguese-language playbook for improving web pages and SPAs across SEO, answer engines, generative discovery, accessibility, and Lighthouse audits. It covers technical markup, structured content, performance practices, and automated validation.
Key features
- 01SEO metadata and sitemap guidance
- 02Schema.org JSON-LD entity graph
- 03Semantic fallback content for SPAs
- 04llms.txt and ARD discovery files
- 05Performance and accessibility practices
- 06Automated Lighthouse 13 validation
Use cases
- 01Improve search metadata on a web page
- 02Make SPA content readable to crawlers
- 03Prepare pages for agentic browsing audits
- 04Validate desktop and mobile Lighthouse results
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ micaelgomestavares/ aeo-geo-bestpractices --skill aeo-geo-bestpracticesAfter installing, type/aeo-geo-bestpracticesin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
LICENSEREADME.mdreferences/templates.mdscripts/run-lighthouse.mjsDetails
From the project README/aeo-geo-bestpractices — SEO + AEO + GEO + Lighthouse 100 Playbook
Workflow completo para transformar qualquer página ou SPA em uma máquina de descoberta orgânica (SEO), motores de resposta (AEO) e motores generativos/agentes de IA (GEO), garantindo simultaneamente 98–100 no Google Lighthouse 13 (Desktop e Mobile) nas 5 categorias: Performance, Accessibility, Best Practices, SEO e Agentic Browsing.
Caminhos: <skill> é a pasta onde este SKILL.md está localizado.
0. Alinhamento Rápido Antes de Executar
Antes de alterar o código, confirme (ou extraia do próprio projeto se já estiver explícito):
- Domínio canônico de produção (ex.:
https://meusite.com.br/). Se ainda não houver domínio definido, pergunte ou use um placeholder claro e avise o usuário. - FAQ Visível vs. Invisível (apenas AEO/GEO):
- Pergunte se o usuário quer a seção de Perguntas Frequentes (FAQ) visível no layout da página (
<details>/<summary>) ou apenas invisível nos bastidores (dentro do@graphJSON-LD +llms.txt+<noscript>) para não alterar o design visual.
- Pergunte se o usuário quer a seção de Perguntas Frequentes (FAQ) visível no layout da página (
1. SEO Técnico Completo (index.html, robots.txt, sitemap.xml)
Consulte os templates prontos em references/templates.md.
- Meta Tags Essenciais no
<head>:<html lang="pt-BR">(ou idioma do projeto).<title>forte (50–65 caracteres) com Nome da Marca/Especialista + Proposta Principal.<meta name="description">(140–165 caracteres) respondendo claramente o que é, para quem é e o que inclui.<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" /><link rel="canonical" href="https://dominio.com/" />+<link rel="alternate" hreflang="pt-BR" ... />ex-default.- Open Graph completo (
og:type,og:locale,og:site_name,og:title,og:description,og:url,og:image,og:image:width,og:image:height,og:image:alt) e Twitter Cards (summary_large_image).
public/robots.txtAmigável para Buscadores e IAs:- Nunca bloqueie bots de busca de IA se o objetivo for GEO. Libere explicitamente (
Allow: /) para:Googlebot,Google-Extended,Bingbot,OAI-SearchBot,GPTBot,ChatGPT-User,PerplexityBot,ClaudeBot,anthropic-ai,Applebot-Extended. - Aponte
Sitemap: https://dominio.com/sitemap.xml.
- Nunca bloqueie bots de busca de IA se o objetivo for GEO. Libere explicitamente (
public/sitemap.xmlRico (Imagens + Vídeo):- Inclua os namespaces
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"exmlns:video="http://www.google.com/schemas/sitemap-video/1.1"quando houver imagens de destaque e vídeo de vendas/apresentação.
- Inclua os namespaces
2. AEO — Answer Engine Optimization (Featured Snippets, Voz e Crawlers sem JS)
Motores de resposta precisam de entidades conectadas e HTML semântico legível sem executar JavaScript:
- Grafo Conectado
@graphemSchema.orgJSON-LD:- Em vez de scripts JSON-LD soltos, crie um único
<script type="application/ld+json">com@graphconectando as entidades por@id(veja o modelo emreferences/templates.md):WebSite(#website)PersonouOrganization(#person/#org) comsameAspara redes sociais oficiaisWebPage(#webpage) comaboutemainEntityProduct/SoftwareApplication/Service(#product) comoffersCourse(#course) quando houver curso/treinamento/bônus educacionalVideoObject(#video) quando houver VSL ou vídeo de apresentaçãoFAQPage(#faq) com 4 a 6 perguntas reais de alta intenção de busca e respostas diretas e completas (40–70 palavras cada).
- Em vez de scripts JSON-LD soltos, crie um único
- Fallback Semântico
<noscript>para SPAs (React / Vue / Vite):- Crawlers de LLMs (
GPTBot,ClaudeBot,PerplexityBot,OAI-SearchBot) frequentemente fazem fetch apenas do HTML bruto e não executam o bundle JavaScript. - Em projetos SPA onde
<div id="root"></div>vem vazio, adicione um bloco<noscript><main>...</main></noscript>noindex.htmlcontendo o<h1>, resumo da oferta, lista de entregáveis (<ul><li>) e link direto para o CTA/checkout. - Importante para Performance: Use
<noscript>(e não elementos dentro de<div id="root">quando usarcreateRoot().render()), pois colocar DOM dentro de#rootsem SSR faz o React desmontar e recriar toda a árvore no mount, atrasando o LCP e gerando TBT.
- Crawlers de LLMs (
3. GEO & Agentic Browsing (Nota 100 no Lighthouse 13)
O Google Lighthouse 13 introduziu a categoria Agentic Browsing, que audita se a página está preparada para agentes autônomos e LLMs (llms-txt e ard-schema).
public/llms.txt+ Link no<head>:- Crie
public/llms.txtem Markdown estruturado (vejareferences/templates.md) contendo:# Nome do Produto / Marca> Resumo em uma frase da proposta de valor- Seções claras:
## Sobre,## O Que Está Incluído,## Bônus / Condições,## Perguntas Frequentes (AEO / GEO),## Links Oficiais.
- No
<head>doindex.html, adicione:<link rel="help" type="text/plain" href="/llms.txt" title="LLMs.txt — Informações estruturadas para IAs" />
- Crie
public/.well-known/ard.json(Agent Resource Discovery v0.91):- Em SPAs (Vite, Next, etc.), rotas inexistentes como
/.well-known/ard.jsonretornam oindex.html(<!doctype html>) por fallback, fazendo a auditoriaard-schemado Lighthouse 13 falhar com erro de parse JSON. - Crie sempre o arquivo
public/.well-known/ard.jsonseguindo o schema oficial ARD v0.91 (modelo exato emreferences/templates.md):- Deve conter
ardVersion: "0.91.0"eentriescomidentifierno formatourn:air:<dominio>:<tipo>:<slug>,displayName,type: "application/agent-skills+md",urlapontando para/llms.txt,descriptionerepresentativeQueries.
- Deve conter
- Em SPAs (Vite, Next, etc.), rotas inexistentes como
4. Google Lighthouse 100/100: Performance & Acessibilidade
Para atingir 98–100 no Mobile (4G Simulado + 4x CPU Throttling) e 100 no Desktop, aplique rigorosamente estas regras:
4.1. LCP (Largest Contentful Paint < 2.1s no Mobile)
- Preload no Topo do
<head>:- Coloque o
<link rel="preload" as="image" ... fetchpriority="high">logo abaixo do<title>(nas primeiras 15 linhas doindex.html), antes das dezenas de meta tags Open Graph e do JSON-LD.
- Coloque o
- Calibragem de
srcSetesizespara o DPR1.75xdo Lighthouse Mobile:- O Lighthouse Mobile emula um Moto G Power (
412pxde largura comdevicePixelRatio: 1.75). - Se uma imagem tiver
sizes="(max-width: 767px) 260px, 500px", o Chrome calcula260 * 1.75 = 455w. Se a versão mobile nosrcSetfor declarada como260w(menor que455w), o Chrome ignora a imagem mobile e baixa a versão desktop pesada! - Regra de ouro: Declare a imagem mobile no
srcSetcom largura>= ceil(largura_css_mobile * 1.8)(ex.:450wpara imagens de240px, ou680wpara imagens de360pxfull-width no mobile) e comprima em WebP (< 30 KB).
- O Lighthouse Mobile emula um Moto G Power (
- Evite que Imagens Decorativas de Fundo "Roubem" o LCP:
- Se a seção Hero tiver uma foto decorativa de fundo (
opacity: 0.15) com caixa (boundingRect) maior que o retrato principal ou<h1>, o Chrome vai considerá-la o elemento LCP. - No mobile (
@media (max-width: 767px)), oculte fotos de fundo gigantes puramente decorativas (display: none) ou reduza suas dimensões para que o elemento principal (pré-carregado comfetchpriority="high") seja o único candidato a LCP.
- Se a seção Hero tiver uma foto decorativa de fundo (
- Não Faça Preload de Fontes que Competem com o JS/CSS Crítico em SPAs:
- Use
font-display: swapno@font-facee deixe o navegador priorizar o download do CSS e do bundle JS inicial antes da fonte secundária.
- Use
4.2. TBT Zero (0ms Total Blocking Time)
- Substitua Animações Contínuas de JS por CSS Compositor +
IntersectionObserver:- Bibliotecas completas de animação no bundle inicial adicionam
50–150 KBde JS e bloqueiam a main thread na hidratação. - Para reveals de scroll, use
IntersectionObservernativo alternando uma classe.is-visiblecomtransition: opacity, transformacelerada por GPU (translate3d). - Para partículas ou rotações contínuas, use
@keyframesem CSS comtransform: translate3d(...)/rotate(...)ewill-change: transform.
- Bibliotecas completas de animação no bundle inicial adicionam
- Cuidado com Filtros SVG (
<feTurbulence>,drop-shadow) e SMIL<animate>no Load:- Nunca use
<feTurbulence>em tela cheia sem dimensões fixas (ele recalcula ruído Perlin em milhões de pixels na CPU, gerando Long Tasks de300ms+). Prefiraradial-gradientleve em CSS. - Nunca combine
filter: drop-shadow(...)em um elemento pai cujo SVG filho sofre mutação de geometria a cada frame no carregamento inicial. Se houver morphing de<path>via<animate attributeName="d">, ative o morphing apenas após a primeira interação do usuário (pointermove,touchstart,wheel) ou após o carregamento inicial (setTimeoutde8000ms), mantendo apenas a rotação CSS na GPU durante o load.
- Nunca use
- Code-Splitting de Smooth Scroll (
Lenis):- Carregue o
Lenisdinamicamente (await import("lenis")) apenas no primeiro eventowheel,touchstartoukeydown({ passive: true, once: true }). Assim ele pesa0 KBe0msde CPU no carregamento inicial.
- Carregue o
- Isole Timers (
setInterval/ Contadores de Urgência) em Componentes Folha:- Nunca coloque um hook
useCountdown(setIntervalde 1s) no componente raiz<App />. Isso força o React a re-renderizar a página inteira a cada segundo durante o teste do Lighthouse. Isole o estado do relógio em um pequeno componente<CountdownClock />que renderiza apenas os dígitos.
- Nunca coloque um hook
4.3. Acessibilidade Nota 100 (WCAG AA)
- Contraste de Cores (
color-contrast):- Textos pequenos sobre fundo escuro (
#10100f/#171512) precisam de razão de contraste>= 4.5:1. Use tons claros para textos secundários (#c4beb4,#d6c5b2) e laranjas luminosos para destaques sobre fundo escuro (#ff9452,#ffa36b). - Botões com fundo laranja vibrante (
#ff772f) devem usar texto escuro (#140c06) para contraste máximo.
- Textos pequenos sobre fundo escuro (
- Consistência entre Texto Visível e Nome Acessível (
label-content-name-mismatch):- Nunca coloque um
aria-labelem um link/botão que não contenha exatamente o texto visível dentro dele (ex.: se a logo dizCF ZANELLA., não coloquearia-label="Início").
- Nunca coloque um
- Semântica e Teclado:
- Inclua
<a class="skip-link" href="#conteudo">Pular para o conteúdo</a>como primeiro foco do<body>. - Use hierarquia estrita de títulos (
h1->h2->h3),aria-labelledbyem todas as<section>, earia-pressedem seletores de estado.
- Inclua
5. Validação Automatizada com Google Lighthouse
Sempre valide as alterações rodando o script automatizado da skill:
# Projeto local (Vite): roda `npm run build` (se existir) e sobe o `vite preview` na porta 4173
node <skill>/scripts/run-lighthouse.mjs
# Pular o build (quando o `dist/` já está atualizado)
node <skill>/scripts/run-lighthouse.mjs --no-build
# Testar uma URL específica (local ou produção), sem build nem preview
node <skill>/scripts/run-lighthouse.mjs https://meusite.com.br
- Sem URL, o script executa
npm run buildquando opackage.jsontiver um scriptbuild, sobe o servidor de preview (vite preview) e roda o Google Lighthouse 13 em Desktop e Mobile. Com URL, testa direto o endereço informado. - Ao final, exibe a tabela de notas das 5 categorias (
performance,accessibility,best-practices,seo,agentic-browsing) e lista detalhadamente qualquer auditoria que não tenha atingido nota máxima para correção imediata. - Requer o Google Chrome instalado. Em projetos que não usam Vite, suba o servidor do próprio framework (ex.:
next start) e passe a URL como argumento.