GEO Score

https://maggion.com.br

Análise: só site técnico

completed

Mesmo site e pergunta — compare o score após corrigir

18GEO Score

Crawlabilidade

9/100

Dados estruturados

29/100

Probe LLM

N/A

Checklist para dev

Exporte tarefas com guias detalhados ou copie um prompt pronto para Cursor/Codex corrigir o site.

Ver histórico do domínio
Pré-visualizar checklist
# GEO Score — Checklist dev

- **Domínio:** https://maggion.com.br
- **Pergunta/dor:** 
- **Score:** 18/100 (red)
- **Audit:** 5ad2fea1-7481-4584-ae2f-afc33588b861 · 2026-10-05

## Tarefas (por impacto)

- [ ] **`P1-RENDER`** · CRITICAL — Conteúdo depende fortemente de JavaScript
  - HTML cru = 5.8% do texto renderizado (limiar 20%)
    - Texto visível sem JS: 189 caracteres
    - Texto visível com JS: 3251 caracteres
    - Sem JS (início): "403 Forbidden Forbidden You don't have permission to access / on this server. Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the"
    - Com JS (início): "Pneus Maggion - Seja qual for o seu veículo Institucional Qualidade Diferenciais e vantagens Sustentabilidade Tudo sobre pneu Blog Treinamentos Revendas Assistência Pneus Motocicle"
  - Ação: Adicione SSR/SSG ou pre-render para crawlers que não executam JS.
  - **Guia:**
    - Confirme o stack (Next.js, Nuxt, React SPA, WordPress, Webflow, etc.).
    - Meça: o HTML inicial da home deve conter texto principal visível sem executar JS.
    - Escolha uma estratégia: SSR/SSG (preferido), pre-render estático, ou renderização híbrida das rotas públicas.
    - Garanta que `<title>`, `<h1>` e parágrafos introdutórios existam no HTML servido ao crawler.
    - Re-teste: ratio texto cru vs renderizado deve ser ≥20%.
    - **Snippets:**
      - Next.js App Router — forçar SSR na página:
        ```
        // app/page.tsx
        export const dynamic = 'force-dynamic' // ou use SSG com generateStaticParams
        
        export default function HomePage() {
          return (
            <>
              <h1>Título principal</h1>
              <p>Descrição do produto visível no HTML inicial.</p>
            </>
          )
        }
        ```
      - Nuxt 3 — SSG/SSR (default em rotas de marketing):
        ```
        // pages/index.vue — evite ClientOnly para conteúdo principal
        <template>
          <h1>{{ title }}</h1>
          <p>{{ intro }}</p>
        </template>
        ```
      - Meta tag fallback (não substitui SSR, só mitiga):
        ```
        <noscript>
          <h1>Título</h1>
          <p>Resumo do produto para crawlers sem JavaScript.</p>
        </noscript>
        ```
    - **Pronto quando:**
      - View Source da home mostra H1 e texto principal sem depender de JS
      - Audit P1-RENDER passa (≥20% do texto renderizado no HTML cru)
    - **Notas:**
      - Se o audit indicou headless indisponível, configure Playwright no worker antes de re-testar.

- [ ] **`P2-JSONLD`** · CRITICAL — JSON-LD ausente
  - Nenhum bloco JSON-LD em https://maggion.com.br/
    - Busca: <script type="application/ld+json"> — 0 ocorrências
    - URL analisada: https://maggion.com.br/
  - Ação: Adicione JSON-LD (Organization, Product/SoftwareApplication, FAQPage).
  - **Guia:**
    - Adicione pelo menos um bloco `<script type="application/ld+json">` na home (ou layout global).
    - Inclua `Organization` ou `SoftwareApplication`/`Product` com name, url, description, logo.
    - Valide JSON (vírgulas, aspas) — JSON inválido é pior que ausência.
    - Opcional: adicione `WebSite` com `potentialAction` SearchAction se houver busca.
    - **Snippets:**
      - Organization + SoftwareApplication:
        ```
        <script type="application/ld+json">
        {
          "@context": "https://schema.org",
          "@graph": [
            {
              "@type": "Organization",
              "name": "Nome da Marca",
              "url": "https://example.com",
              "logo": "https://example.com/logo.png"
            },
            {
              "@type": "SoftwareApplication",
              "name": "Nome do Produto",
              "applicationCategory": "BusinessApplication",
              "operatingSystem": "Web",
              "description": "O que o produto faz em uma frase.",
              "url": "https://example.com"
            }
          ]
        }
        </script>
        ```
    - **Pronto quando:**
      - ≥1 bloco JSON-LD válido no HTML da home
      - Audit P2-JSONLD passa

- [ ] **`P1-ROBOTS-EXISTS`** · HIGH — robots.txt ausente ou inacessível
  - GET https://maggion.com.br/robots.txt → HTTP 403
    - URL testada: https://maggion.com.br/robots.txt
  - Ação: Publique um robots.txt em /robots.txt referenciando o sitemap e permitindo crawlers de IA.
  - **Guia:**
    - Crie o arquivo `public/robots.txt` (ou equivalente na raiz do site servido em `/robots.txt`).
    - Permita crawlers públicos e bots de IA nas páginas de marketing (home, produto, blog, docs).
    - Adicione a linha `Sitemap:` apontando para o sitemap canônico (HTTPS).
    - Faça deploy e valide com `curl -I https://seudominio/robots.txt` → HTTP 200.
    - **Snippets:**
      - robots.txt mínimo:
        ```
        User-agent: *
        Allow: /
        
        User-agent: GPTBot
        Allow: /
        
        User-agent: ClaudeBot
        Allow: /
        
        User-agent: PerplexityBot
        Allow: /
        
        Sitemap: https://example.com/sitemap.xml
        ```
    - **Pronto quando:**
      - GET /robots.txt retorna HTTP 200 com conteúdo text/plain
      - Audit P1-ROBOTS-EXISTS passa

- [ ] **`P1-SITEMAP`** · HIGH — sitemap.xml ausente ou vazio
  - sitemap → HTTP 403, 0 URL(s)
    - Testado: https://maggion.com.br/sitemap.xml
  - Ação: Publique um sitemap.xml com as URLs canônicas do site.
  - **Guia:**
    - Gere um `sitemap.xml` com URLs canônicas HTTPS (home, produto, principais landings, blog).
    - Configure o CMS/framework para atualizar o sitemap ao publicar páginas.
    - Referencie o sitemap no `robots.txt` (linha `Sitemap:`).
    - Submeta o sitemap no Google Search Console (opcional, mas recomendado).
    - **Snippets:**
      - sitemap.xml mínimo:
        ```
        <?xml version="1.0" encoding="UTF-8"?>
        <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
          <url>
            <loc>https://example.com/</loc>
            <changefreq>weekly</changefreq>
            <priority>1.0</priority>
          </url>
          <url>
            <loc>https://example.com/pricing</loc>
          </url>
        </urlset>
        ```
    - **Pronto quando:**
      - GET /sitemap.xml → HTTP 200 com ≥1 URL
      - Audit P1-SITEMAP passa

- [ ] **`P1-STATUS`** · HIGH — Status HTTP da home problemático
  - HTTP 403, 0 redirect(s)
    - URL: https://maggion.com.br
    - Status: 403
    - Redirects: 0
  - Ação: Garanta HTTP 200 na URL canônica com no máximo 1 redirect.
  - **Guia:**
    - Acesse a URL canônica do domínio (com HTTPS) e verifique o status HTTP.
    - Corrija cadeia de redirects: máximo 1 hop até a URL final (idealmente zero).
    - Resolva 404/5xx na home — verifique DNS, certificado SSL e config do servidor/CDN.
    - Configure redirect 301 de `http://` e `www` para a versão canônica escolhida.
    - **Pronto quando:**
      - URL canônica responde HTTP 200
      - ≤1 redirect na cadeia
      - Audit P1-STATUS passa

- [ ] **`P1-LLMS-TXT`** · MEDIUM — llms.txt ausente
  - GET https://maggion.com.br/llms.txt → HTTP 403
    - URL testada: https://maggion.com.br/llms.txt
    - Raiz = mapa; detalhes por página = Markdown linkado (não um arquivo único gigante)
    - Declare rel=alternate / describedby nas páginas importantes
  - Ação: Crie /llms.txt na raiz (índice leve: o que é, FAQ, links). Se o conteúdo varia por página, publique .md por URL e liste no índice — ver guia do finding.
  - **Guia:**
    - Crie `/llms.txt` na raiz (ex.: `public/llms.txt`) — obrigatório para o GEO Score e ponto de entrada dos agentes.
    - Trate a raiz como **índice leve**: H1 com o nome, blockquote com o que é / para quem, seções curtas (problema, público, FAQ) e uma lista de links Markdown para páginas-chave.
    - Se o site tem conteúdo distinto por página/seção: **não** cole tudo num único arquivo gigante. Publique Markdown por URL importante (ex.: `/precos.md`, `/produto/x.md`) ou `llms.txt` por escopo (ex.: `/docs/llms.txt`).
    - No `/llms.txt` raiz, liste esses arquivos: `- [Preços](https://seudominio/precos.md): planos e condições`.
    - Na HTML de cada página importante, declare descoberta: `<link rel="alternate" type="text/markdown" href="…">` e/ou `<link rel="describedby" href="/llms.txt">` (ou o llms do escopo). Alternativa: header HTTP `Link`.
    - Mantenha o HTML da página rico (H1, abertura, FAQ) — busca grounded (Perplexity etc.) ainda cita HTML; llms.txt/MD reforçam contexto, não substituem a página.
    - Faça deploy e valide: `curl https://seudominio/llms.txt` e os `.md` linkados.
    - **Snippets:**
      - llms.txt raiz (índice + links):
        ```
        # Nome do Produto / Marca
        
        > Descrição direta em 1–2 frases: o que é, para quem, principal benefício.
        
        ## O que resolve
        
        - Problema 1
        - Problema 2
        
        ## Para quem é
        
        - Público A
        - Público B
        
        ## Perguntas frequentes
        
        ### O que é [produto]?
        Resposta direta.
        
        ## Docs e páginas (Markdown)
        
        - [Home](https://example.com/): visão geral
        - [Preços](https://example.com/precos.md): planos e condições
        - [Produto X](https://example.com/produtos/x.md): para quem é e diferencial
        - [FAQ](https://example.com/faq.md): objeções comuns
        
        ## Links HTML
        
        - Site: https://example.com
        - Contato: https://example.com/contato
        ```
      - Markdown por página (ex.: /precos.md):
        ```
        # Preços — Nome do Produto
        
        > Planos para [público]. Sem cartão no trial.
        
        ## Planos
        
        - Starter: …
        - Pro: …
        
        ## Perguntas frequentes
        
        ### Tem teste grátis?
        Sim, X dias.
        ```
      - Descoberta no HTML / header:
        ```
        <!-- no <head> da página /precos -->
        <link rel="alternate" type="text/markdown" href="https://example.com/precos.md" />
        <link rel="describedby" href="https://example.com/llms.txt" />
        
        # ou HTTP:
        # Link: </precos.md>; rel="alternate"; type="text/markdown", </llms.txt>; rel="describedby"
        ```
    - **Pronto quando:**
      - GET /llms.txt → HTTP 200 com conteúdo Markdown
      - Arquivo tem título H1, pelo menos 2 seções H2 e ≥100 palavras
      - Audit P1-LLMS-TXT passa
      - (Recomendado) Páginas-chave têm .md ou llms de escopo linkados a partir da raiz
    - **Notas:**
      - Padrão llmstxt.org: raiz = mapa; conteúdo específico = links / subpaths; o mais específico cobre o escopo.
      - LLMs preferem Markdown limpo sob demanda. Arquivo único enorme estoura contexto e é pior que índice + pedaços.
      - O audit v1 só valida /llms.txt na home — MD por página não sobe a nota, mas melhora citação correta.
      - Opcional: /llms-full.txt com texto concatenado para agentes que pedem contexto completo (manutenção mais cara).

- [ ] **`P1-LINK-HEADERS`** · MEDIUM — Headers HTTP Link (RFC 8288) ausentes
  - GET https://maggion.com.br/ sem header Link — agentes não descobrem llms.txt, sitemap ou API pelo HTTP
    - Não confundir com <link> no HTML (canonical no <head> não conta). O check lê o header HTTP Link.
    - Formato: Link: </llms.txt>; rel="describedby"; type="text/markdown"
    - Nenhum header Link na resposta da home
  - Ação: Adicione headers Link na home apontando para /llms.txt, sitemap e, se houver API, /.well-known/api-catalog.
  - **Guia:**
    - Confirme que o check é o header HTTP `Link`, não a tag HTML `<link rel="canonical">`.
    - Na home, envie pelo menos um `Link` apontando para recursos que agentes devem descobrir: `/llms.txt`, `/sitemap.xml`, docs de API se existirem.
    - Em hosting estático: `_headers` (Netlify/Cloudflare Pages), `nitro.routeRules`, ou config do CDN/nginx.
    - Valide: `curl -sI https://seudominio.com/ | findstr /i Link` (Windows) ou `curl -sI … | grep -i ^link`.
    - **Snippets:**
      - Headers HTTP (RFC 8288):
        ```
        Link: </llms.txt>; rel="describedby"; type="text/markdown"
        Link: </sitemap.xml>; rel="index"
        Link: </.well-known/api-catalog>; rel="api-catalog"
        ```
      - Nuxt — nitro.routeRules:
        ```
        nitro: {
          routeRules: {
            '/': {
              headers: {
                Link: '</llms.txt>; rel="describedby"; type="text/markdown", </sitemap.xml>; rel="index"',
              },
            },
          },
        },
        ```
      - Cloudflare Pages / Netlify — public/_headers:
        ```
        /
          Link: </llms.txt>; rel="describedby"; type="text/markdown"
          Link: </sitemap.xml>; rel="index"
        ```
    - **Pronto quando:**
      - GET / inclui header Link com rel de descoberta (describedby, index, api-catalog ou service-doc)
      - Audit P1-LINK-HEADERS passa
    - **Notas:**
      - Verificado pelo isitagentready.com (Discoverability).
      - Landing sem API: describedby → llms.txt + index → sitemap já basta. api-catalog só se houver catálogo RFC 9727.

- [ ] **`P2-OPENING`** · MEDIUM — Abertura pouco extratível
  - Primeiros parágrafos não definem o produto claramente
    - Parágrafo 1 (53 chars): "You don't have permission to access / on this server."
    - Parágrafo 2 (111 chars): "Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the request."
  - Ação: Defina o produto de forma direta nos 2 primeiros parágrafos ("X é uma ferramenta de Y que Z").
  - **Guia:**
    - Se a evidência indicar SPA / HTML cru sem <p>: ative SSR/SSG primeiro (P1-RENDER) — reescrever copy no Hero.vue não coloca texto no HTML inicial.
    - Com HTML populado: reescreva os 2 primeiros parágrafos acima da dobra.
    - Primeira frase: "[Marca] é [categoria] que [benefício principal]."
    - Segunda frase: público-alvo ou diferencial concreto.
    - Evite abrir só com slogans ou CTAs.
    - **Snippets:**
      - Modelo de abertura:
        ```
        <p>Acme é uma plataforma de gestão de tempo para equipes remotas que integra timesheet, aprovações e relatórios em um só lugar.</p>
        <p>Indicada para agências e consultorias B2B que cobram por hora e usam Slack no dia a dia.</p>
        ```
    - **Pronto quando:**
      - View Source mostra parágrafo de abertura >50 chars com definição clara
      - Audit P2-OPENING passa
    - **Notas:**
      - GEO mede o HTML cru. Texto só após JS = abertura “ausente” para crawlers.

- [ ] **`P2-CANONICAL`** · MEDIUM — URL canônica (<link rel="canonical">) ausente
  - Nenhum <link rel="canonical"> encontrado em https://maggion.com.br/
    - Página analisada: https://maggion.com.br/
    - O canonical evita conteúdo duplicado e ajuda motores de IA a identificar a URL autoritativa.
  - Ação: Adicione <link rel="canonical" href="https://seudominio.com/"> no <head> de cada página.
  - **Guia:**
    - Adicione `<link rel="canonical" href="URL_CANÔNICA">` no `<head>` de cada página.
    - A URL deve ser absoluta (https://), apontar para a versão preferida da página.
    - Para Nuxt: use `useHead({ link: [{ rel: "canonical", href: url }] })` ou configure no `nuxt.config`.
    - Para Next.js: use `<Head><link rel="canonical" href={url} /></Head>` ou metadata API.
    - **Snippets:**
      - HTML direto:
        ```
        <link rel="canonical" href="https://example.com/" />
        ```
      - Nuxt 3 (nuxt.config.js — head global):
        ```
        head: {
          link: [
            { rel: 'canonical', href: 'https://example.com/' }
          ]
        }
        ```
    - **Pronto quando:**
      - <link rel="canonical"> presente no HTML com URL HTTPS válida
      - Audit P2-CANONICAL passa

- [ ] **`P2-META`** · MEDIUM — Metadados incompletos
  - title, meta description ou og:title ausentes ou muito curtos
    - title (13 chars): "403 Forbidden"
    - meta description: (ausente)
    - og:title: (ausente)
  - Ação: Preencha title, meta description e og:title com texto descritivo (>10 chars).
  - **Guia:**
    - Preencha `<title>` único e descritivo (marca + proposta de valor, ~50–60 chars).
    - Adicione `<meta name="description">` com benefício claro (~120–160 chars).
    - Configure `<meta property="og:title">` (pode espelhar title ou ser mais marketing).
    - Opcional: `og:description` e `og:image` para compartilhamento.
    - **Snippets:**
      - Meta tags mínimas:
        ```
        <title>Acme — Gestão de tempo para equipes remotas</title>
        <meta name="description" content="Controle horas, aprovações e relatórios. Integração com Slack. Teste grátis.">
        <meta property="og:title" content="Acme — Gestão de tempo para equipes remotas">
        ```
    - **Pronto quando:**
      - title, meta description e og:title presentes com >10 caracteres cada
      - Audit P2-META passa
    - **Notas:**
      - Compare com os valores ausentes/curtos listados na evidência do audit.

- [ ] **`P1-AI-TXT`** · LOW — Content Signals (ai.txt) ausente
  - GET https://maggion.com.br/.well-known/ai.txt → HTTP 403
    - URL testada: https://maggion.com.br/.well-known/ai.txt
    - Declarar política aumenta confiança de agentes e pode melhorar indexação em motores que respeitam Content Signals.
  - Ação: Crie /.well-known/ai.txt declarando sua política de uso por IA (treino, busca, inferência).
  - **Guia:**
    - Crie o diretório `public/.well-known/` se não existir.
    - Crie o arquivo `ai.txt` declarando sua política de uso do conteúdo para IA.
    - Deploy e valide com `curl https://seudominio/.well-known/ai.txt`.
    - **Snippets:**
      - ai.txt mínimo (permite busca e inferência, nega treino):
        ```
        # AI Usage Policy — https://seudominio.com
        # Baseado no padrão Content Signals (isitagentready.com)
        
        Allow: search
        Allow: inference
        Disallow: training
        ```
      - ai.txt permissivo (permite tudo):
        ```
        # AI Usage Policy
        Allow: search
        Allow: inference
        Allow: training
        ```
    - **Pronto quando:**
      - GET /.well-known/ai.txt → HTTP 200
      - Arquivo declara pelo menos Allow: search e Allow: inference
      - Audit P1-AI-TXT passa
    - **Notas:**
      - Content Signals é verificado pelo Cloudflare isitagentready.com e está se tornando padrão.
      - Negar treino mas permitir search/inference é o padrão mais seguro para a maioria dos sites.

- [ ] **`P1-MARKDOWN`** · LOW — Servidor não serve Markdown por negociação de conteúdo
  - Requisição com Accept: text/markdown não retornou text/markdown
    - LLMs preferem Markdown limpo a HTML — menos tokens, menos ruído.
    - Para Nuxt/Next.js: adicione um endpoint /api/content ou middleware de content negotiation.
    - Para sites estáticos: serve /llms.txt já cobre a maioria dos casos práticos.
  - Ação: Configure o servidor/framework para responder com Markdown quando solicitado via Accept: text/markdown.
  - **Guia:**
    - Avalie se faz sentido para seu stack — sites estáticos já têm /llms.txt como alternativa mais simples.
    - Para Nuxt/Next.js: adicione middleware que, quando `Accept: text/markdown` for enviado, sirva uma versão Markdown da página.
    - Para sites estáticos: garanta que /llms.txt esteja rico — é o equivalente prático.
    - **Snippets:**
      - Nuxt server middleware (server/middleware/markdown.ts):
        ```
        export default defineEventHandler(async (event) => {
          const accept = getHeader(event, 'accept') ?? ''
          if (!accept.includes('text/markdown')) return
        
          // Redireciona para versão Markdown equivalente
          const url = getRequestURL(event)
          if (url.pathname === '/') {
            setHeader(event, 'content-type', 'text/markdown; charset=utf-8')
            // retorne o conteúdo Markdown da home
            return '# Worklift\n\nDescrição Markdown da home...'
          }
        })
        ```
    - **Pronto quando:**
      - GET / com Accept: text/markdown retorna Content-Type: text/markdown
      - Audit P1-MARKDOWN passa
    - **Notas:**
      - Este check tem impacto prático menor que llms.txt — priorize os outros primeiro.

## Prompt para code agent (todos os findings)

Copie o bloco abaixo para Cursor/Codex:

```
Você está corrigindo múltiplos problemas de GEO (Generative Engine Optimization) em um site.
Trabalhe por ordem de severidade. Mudanças mínimas, estilo consistente.

## Contexto
- Domínio: https://maggion.com.br
- Pergunta/dor: 
- Score atual: 18/100
- Audit ID: 5ad2fea1-7481-4584-ae2f-afc33588b861

## 12 finding(s) a tratar

---
### 1. P1-RENDER — Conteúdo depende fortemente de JavaScript (critical)

HTML cru = 5.8% do texto renderizado (limiar 20%)

Detalhes coletados:
- Texto visível sem JS: 189 caracteres
- Texto visível com JS: 3251 caracteres
- Sem JS (início): "403 Forbidden Forbidden You don't have permission to access / on this server. Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the"
- Com JS (início): "Pneus Maggion - Seja qual for o seu veículo Institucional Qualidade Diferenciais e vantagens Sustentabilidade Tudo sobre pneu Blog Treinamentos Revendas Assistência Pneus Motocicle"

**Ação resumida:** Adicione SSR/SSG ou pre-render para crawlers que não executam JS.

## Passos
1. Confirme o stack (Next.js, Nuxt, React SPA, WordPress, Webflow, etc.).
2. Meça: o HTML inicial da home deve conter texto principal visível sem executar JS.
3. Escolha uma estratégia: SSR/SSG (preferido), pre-render estático, ou renderização híbrida das rotas públicas.
4. Garanta que `<title>`, `<h1>` e parágrafos introdutórios existam no HTML servido ao crawler.
5. Re-teste: ratio texto cru vs renderizado deve ser ≥20%.

## Snippets (adapte ao stack do projeto)

### Next.js App Router — forçar SSR na página
```
// app/page.tsx
export const dynamic = 'force-dynamic' // ou use SSG com generateStaticParams

export default function HomePage() {
  return (
    <>
      <h1>Título principal</h1>
      <p>Descrição do produto visível no HTML inicial.</p>
    </>
  )
}
```

### Nuxt 3 — SSG/SSR (default em rotas de marketing)
```
// pages/index.vue — evite ClientOnly para conteúdo principal
<template>
  <h1>{{ title }}</h1>
  <p>{{ intro }}</p>
</template>
```

### Meta tag fallback (não substitui SSR, só mitiga)
```
<noscript>
  <h1>Título</h1>
  <p>Resumo do produto para crawlers sem JavaScript.</p>
</noscript>
```

## Definition of done
- View Source da home mostra H1 e texto principal sem depender de JS
- Audit P1-RENDER passa (≥20% do texto renderizado no HTML cru)

## Notas
- Se o audit indicou headless indisponível, configure Playwright no worker antes de re-testar.
---
### 2. P2-JSONLD — JSON-LD ausente (critical)

Nenhum bloco JSON-LD em https://maggion.com.br/

Detalhes coletados:
- Busca: <script type="application/ld+json"> — 0 ocorrências
- URL analisada: https://maggion.com.br/

**Ação resumida:** Adicione JSON-LD (Organization, Product/SoftwareApplication, FAQPage).

## Passos
1. Adicione pelo menos um bloco `<script type="application/ld+json">` na home (ou layout global).
2. Inclua `Organization` ou `SoftwareApplication`/`Product` com name, url, description, logo.
3. Valide JSON (vírgulas, aspas) — JSON inválido é pior que ausência.
4. Opcional: adicione `WebSite` com `potentialAction` SearchAction se houver busca.

## Snippets (adapte ao stack do projeto)

### Organization + SoftwareApplication
```
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "name": "Nome da Marca",
      "url": "https://example.com",
      "logo": "https://example.com/logo.png"
    },
    {
      "@type": "SoftwareApplication",
      "name": "Nome do Produto",
      "applicationCategory": "BusinessApplication",
      "operatingSystem": "Web",
      "description": "O que o produto faz em uma frase.",
      "url": "https://example.com"
    }
  ]
}
</script>
```

## Definition of done
- ≥1 bloco JSON-LD válido no HTML da home
- Audit P2-JSONLD passa
---
### 3. P1-ROBOTS-EXISTS — robots.txt ausente ou inacessível (high)

GET https://maggion.com.br/robots.txt → HTTP 403

Detalhes coletados:
- URL testada: https://maggion.com.br/robots.txt

**Ação resumida:** Publique um robots.txt em /robots.txt referenciando o sitemap e permitindo crawlers de IA.

## Passos
1. Crie o arquivo `public/robots.txt` (ou equivalente na raiz do site servido em `/robots.txt`).
2. Permita crawlers públicos e bots de IA nas páginas de marketing (home, produto, blog, docs).
3. Adicione a linha `Sitemap:` apontando para o sitemap canônico (HTTPS).
4. Faça deploy e valide com `curl -I https://seudominio/robots.txt` → HTTP 200.

## Snippets (adapte ao stack do projeto)

### robots.txt mínimo
```
User-agent: *
Allow: /

User-agent: GPTBot
Allow: /

User-agent: ClaudeBot
Allow: /

User-agent: PerplexityBot
Allow: /

Sitemap: https://example.com/sitemap.xml
```

## Definition of done
- GET /robots.txt retorna HTTP 200 com conteúdo text/plain
- Audit P1-ROBOTS-EXISTS passa
---
### 4. P1-SITEMAP — sitemap.xml ausente ou vazio (high)

sitemap → HTTP 403, 0 URL(s)

Detalhes coletados:
- Testado: https://maggion.com.br/sitemap.xml

**Ação resumida:** Publique um sitemap.xml com as URLs canônicas do site.

## Passos
1. Gere um `sitemap.xml` com URLs canônicas HTTPS (home, produto, principais landings, blog).
2. Configure o CMS/framework para atualizar o sitemap ao publicar páginas.
3. Referencie o sitemap no `robots.txt` (linha `Sitemap:`).
4. Submeta o sitemap no Google Search Console (opcional, mas recomendado).

## Snippets (adapte ao stack do projeto)

### sitemap.xml mínimo
```
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
    <changefreq>weekly</changefreq>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://example.com/pricing</loc>
  </url>
</urlset>
```

## Definition of done
- GET /sitemap.xml → HTTP 200 com ≥1 URL
- Audit P1-SITEMAP passa
---
### 5. P1-STATUS — Status HTTP da home problemático (high)

HTTP 403, 0 redirect(s)

Detalhes coletados:
- URL: https://maggion.com.br
- Status: 403
- Redirects: 0

**Ação resumida:** Garanta HTTP 200 na URL canônica com no máximo 1 redirect.

## Passos
1. Acesse a URL canônica do domínio (com HTTPS) e verifique o status HTTP.
2. Corrija cadeia de redirects: máximo 1 hop até a URL final (idealmente zero).
3. Resolva 404/5xx na home — verifique DNS, certificado SSL e config do servidor/CDN.
4. Configure redirect 301 de `http://` e `www` para a versão canônica escolhida.

## Definition of done
- URL canônica responde HTTP 200
- ≤1 redirect na cadeia
- Audit P1-STATUS passa
---
### 6. P1-LLMS-TXT — llms.txt ausente (medium)

GET https://maggion.com.br/llms.txt → HTTP 403

Detalhes coletados:
- URL testada: https://maggion.com.br/llms.txt
- Raiz = mapa; detalhes por página = Markdown linkado (não um arquivo único gigante)
- Declare rel=alternate / describedby nas páginas importantes

**Ação resumida:** Crie /llms.txt na raiz (índice leve: o que é, FAQ, links). Se o conteúdo varia por página, publique .md por URL e liste no índice — ver guia do finding.

## Passos
1. Crie `/llms.txt` na raiz (ex.: `public/llms.txt`) — obrigatório para o GEO Score e ponto de entrada dos agentes.
2. Trate a raiz como **índice leve**: H1 com o nome, blockquote com o que é / para quem, seções curtas (problema, público, FAQ) e uma lista de links Markdown para páginas-chave.
3. Se o site tem conteúdo distinto por página/seção: **não** cole tudo num único arquivo gigante. Publique Markdown por URL importante (ex.: `/precos.md`, `/produto/x.md`) ou `llms.txt` por escopo (ex.: `/docs/llms.txt`).
4. No `/llms.txt` raiz, liste esses arquivos: `- [Preços](https://seudominio/precos.md): planos e condições`.
5. Na HTML de cada página importante, declare descoberta: `<link rel="alternate" type="text/markdown" href="…">` e/ou `<link rel="describedby" href="/llms.txt">` (ou o llms do escopo). Alternativa: header HTTP `Link`.
6. Mantenha o HTML da página rico (H1, abertura, FAQ) — busca grounded (Perplexity etc.) ainda cita HTML; llms.txt/MD reforçam contexto, não substituem a página.
7. Faça deploy e valide: `curl https://seudominio/llms.txt` e os `.md` linkados.

## Snippets (adapte ao stack do projeto)

### llms.txt raiz (índice + links)
```
# Nome do Produto / Marca

> Descrição direta em 1–2 frases: o que é, para quem, principal benefício.

## O que resolve

- Problema 1
- Problema 2

## Para quem é

- Público A
- Público B

## Perguntas frequentes

### O que é [produto]?
Resposta direta.

## Docs e páginas (Markdown)

- [Home](https://example.com/): visão geral
- [Preços](https://example.com/precos.md): planos e condições
- [Produto X](https://example.com/produtos/x.md): para quem é e diferencial
- [FAQ](https://example.com/faq.md): objeções comuns

## Links HTML

- Site: https://example.com
- Contato: https://example.com/contato
```

### Markdown por página (ex.: /precos.md)
```
# Preços — Nome do Produto

> Planos para [público]. Sem cartão no trial.

## Planos

- Starter: …
- Pro: …

## Perguntas frequentes

### Tem teste grátis?
Sim, X dias.
```

### Descoberta no HTML / header
```
<!-- no <head> da página /precos -->
<link rel="alternate" type="text/markdown" href="https://example.com/precos.md" />
<link rel="describedby" href="https://example.com/llms.txt" />

# ou HTTP:
# Link: </precos.md>; rel="alternate"; type="text/markdown", </llms.txt>; rel="describedby"
```

## Definition of done
- GET /llms.txt → HTTP 200 com conteúdo Markdown
- Arquivo tem título H1, pelo menos 2 seções H2 e ≥100 palavras
- Audit P1-LLMS-TXT passa
- (Recomendado) Páginas-chave têm .md ou llms de escopo linkados a partir da raiz

## Notas
- Padrão llmstxt.org: raiz = mapa; conteúdo específico = links / subpaths; o mais específico cobre o escopo.
- LLMs preferem Markdown limpo sob demanda. Arquivo único enorme estoura contexto e é pior que índice + pedaços.
- O audit v1 só valida /llms.txt na home — MD por página não sobe a nota, mas melhora citação correta.
- Opcional: /llms-full.txt com texto concatenado para agentes que pedem contexto completo (manutenção mais cara).
---
### 7. P1-LINK-HEADERS — Headers HTTP Link (RFC 8288) ausentes (medium)

GET https://maggion.com.br/ sem header Link — agentes não descobrem llms.txt, sitemap ou API pelo HTTP

Detalhes coletados:
- Não confundir com <link> no HTML (canonical no <head> não conta). O check lê o header HTTP Link.
- Formato: Link: </llms.txt>; rel="describedby"; type="text/markdown"
- Nenhum header Link na resposta da home

**Ação resumida:** Adicione headers Link na home apontando para /llms.txt, sitemap e, se houver API, /.well-known/api-catalog.

## Passos
1. Confirme que o check é o header HTTP `Link`, não a tag HTML `<link rel="canonical">`.
2. Na home, envie pelo menos um `Link` apontando para recursos que agentes devem descobrir: `/llms.txt`, `/sitemap.xml`, docs de API se existirem.
3. Em hosting estático: `_headers` (Netlify/Cloudflare Pages), `nitro.routeRules`, ou config do CDN/nginx.
4. Valide: `curl -sI https://seudominio.com/ | findstr /i Link` (Windows) ou `curl -sI … | grep -i ^link`.

## Snippets (adapte ao stack do projeto)

### Headers HTTP (RFC 8288)
```
Link: </llms.txt>; rel="describedby"; type="text/markdown"
Link: </sitemap.xml>; rel="index"
Link: </.well-known/api-catalog>; rel="api-catalog"
```

### Nuxt — nitro.routeRules
```
nitro: {
  routeRules: {
    '/': {
      headers: {
        Link: '</llms.txt>; rel="describedby"; type="text/markdown", </sitemap.xml>; rel="index"',
      },
    },
  },
},
```

### Cloudflare Pages / Netlify — public/_headers
```
/
  Link: </llms.txt>; rel="describedby"; type="text/markdown"
  Link: </sitemap.xml>; rel="index"
```

## Definition of done
- GET / inclui header Link com rel de descoberta (describedby, index, api-catalog ou service-doc)
- Audit P1-LINK-HEADERS passa

## Notas
- Verificado pelo isitagentready.com (Discoverability).
- Landing sem API: describedby → llms.txt + index → sitemap já basta. api-catalog só se houver catálogo RFC 9727.
---
### 8. P2-OPENING — Abertura pouco extratível (medium)

Primeiros parágrafos não definem o produto claramente

Detalhes coletados:
- Parágrafo 1 (53 chars): "You don't have permission to access / on this server."
- Parágrafo 2 (111 chars): "Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the request."

**Ação resumida:** Defina o produto de forma direta nos 2 primeiros parágrafos ("X é uma ferramenta de Y que Z").

## Passos
1. Se a evidência indicar SPA / HTML cru sem <p>: ative SSR/SSG primeiro (P1-RENDER) — reescrever copy no Hero.vue não coloca texto no HTML inicial.
2. Com HTML populado: reescreva os 2 primeiros parágrafos acima da dobra.
3. Primeira frase: "[Marca] é [categoria] que [benefício principal]."
4. Segunda frase: público-alvo ou diferencial concreto.
5. Evite abrir só com slogans ou CTAs.

## Snippets (adapte ao stack do projeto)

### Modelo de abertura
```
<p>Acme é uma plataforma de gestão de tempo para equipes remotas que integra timesheet, aprovações e relatórios em um só lugar.</p>
<p>Indicada para agências e consultorias B2B que cobram por hora e usam Slack no dia a dia.</p>
```

## Definition of done
- View Source mostra parágrafo de abertura >50 chars com definição clara
- Audit P2-OPENING passa

## Notas
- GEO mede o HTML cru. Texto só após JS = abertura “ausente” para crawlers.
---
### 9. P2-CANONICAL — URL canônica (<link rel="canonical">) ausente (medium)

Nenhum <link rel="canonical"> encontrado em https://maggion.com.br/

Detalhes coletados:
- Página analisada: https://maggion.com.br/
- O canonical evita conteúdo duplicado e ajuda motores de IA a identificar a URL autoritativa.

**Ação resumida:** Adicione <link rel="canonical" href="https://seudominio.com/"> no <head> de cada página.

## Passos
1. Adicione `<link rel="canonical" href="URL_CANÔNICA">` no `<head>` de cada página.
2. A URL deve ser absoluta (https://), apontar para a versão preferida da página.
3. Para Nuxt: use `useHead({ link: [{ rel: "canonical", href: url }] })` ou configure no `nuxt.config`.
4. Para Next.js: use `<Head><link rel="canonical" href={url} /></Head>` ou metadata API.

## Snippets (adapte ao stack do projeto)

### HTML direto
```
<link rel="canonical" href="https://example.com/" />
```

### Nuxt 3 (nuxt.config.js — head global)
```
head: {
  link: [
    { rel: 'canonical', href: 'https://example.com/' }
  ]
}
```

## Definition of done
- <link rel="canonical"> presente no HTML com URL HTTPS válida
- Audit P2-CANONICAL passa
---
### 10. P2-META — Metadados incompletos (medium)

title, meta description ou og:title ausentes ou muito curtos

Detalhes coletados:
- title (13 chars): "403 Forbidden"
- meta description: (ausente)
- og:title: (ausente)

**Ação resumida:** Preencha title, meta description e og:title com texto descritivo (>10 chars).

## Passos
1. Preencha `<title>` único e descritivo (marca + proposta de valor, ~50–60 chars).
2. Adicione `<meta name="description">` com benefício claro (~120–160 chars).
3. Configure `<meta property="og:title">` (pode espelhar title ou ser mais marketing).
4. Opcional: `og:description` e `og:image` para compartilhamento.

## Snippets (adapte ao stack do projeto)

### Meta tags mínimas
```
<title>Acme — Gestão de tempo para equipes remotas</title>
<meta name="description" content="Controle horas, aprovações e relatórios. Integração com Slack. Teste grátis.">
<meta property="og:title" content="Acme — Gestão de tempo para equipes remotas">
```

## Definition of done
- title, meta description e og:title presentes com >10 caracteres cada
- Audit P2-META passa

## Notas
- Compare com os valores ausentes/curtos listados na evidência do audit.
---
### 11. P1-AI-TXT — Content Signals (ai.txt) ausente (low)

GET https://maggion.com.br/.well-known/ai.txt → HTTP 403

Detalhes coletados:
- URL testada: https://maggion.com.br/.well-known/ai.txt
- Declarar política aumenta confiança de agentes e pode melhorar indexação em motores que respeitam Content Signals.

**Ação resumida:** Crie /.well-known/ai.txt declarando sua política de uso por IA (treino, busca, inferência).

## Passos
1. Crie o diretório `public/.well-known/` se não existir.
2. Crie o arquivo `ai.txt` declarando sua política de uso do conteúdo para IA.
3. Deploy e valide com `curl https://seudominio/.well-known/ai.txt`.

## Snippets (adapte ao stack do projeto)

### ai.txt mínimo (permite busca e inferência, nega treino)
```
# AI Usage Policy — https://seudominio.com
# Baseado no padrão Content Signals (isitagentready.com)

Allow: search
Allow: inference
Disallow: training
```

### ai.txt permissivo (permite tudo)
```
# AI Usage Policy
Allow: search
Allow: inference
Allow: training
```

## Definition of done
- GET /.well-known/ai.txt → HTTP 200
- Arquivo declara pelo menos Allow: search e Allow: inference
- Audit P1-AI-TXT passa

## Notas
- Content Signals é verificado pelo Cloudflare isitagentready.com e está se tornando padrão.
- Negar treino mas permitir search/inference é o padrão mais seguro para a maioria dos sites.
---
### 12. P1-MARKDOWN — Servidor não serve Markdown por negociação de conteúdo (low)

Requisição com Accept: text/markdown não retornou text/markdown

Detalhes coletados:
- LLMs preferem Markdown limpo a HTML — menos tokens, menos ruído.
- Para Nuxt/Next.js: adicione um endpoint /api/content ou middleware de content negotiation.
- Para sites estáticos: serve /llms.txt já cobre a maioria dos casos práticos.

**Ação resumida:** Configure o servidor/framework para responder com Markdown quando solicitado via Accept: text/markdown.

## Passos
1. Avalie se faz sentido para seu stack — sites estáticos já têm /llms.txt como alternativa mais simples.
2. Para Nuxt/Next.js: adicione middleware que, quando `Accept: text/markdown` for enviado, sirva uma versão Markdown da página.
3. Para sites estáticos: garanta que /llms.txt esteja rico — é o equivalente prático.

## Snippets (adapte ao stack do projeto)

### Nuxt server middleware (server/middleware/markdown.ts)
```
export default defineEventHandler(async (event) => {
  const accept = getHeader(event, 'accept') ?? ''
  if (!accept.includes('text/markdown')) return

  // Redireciona para versão Markdown equivalente
  const url = getRequestURL(event)
  if (url.pathname === '/') {
    setHeader(event, 'content-type', 'text/markdown; charset=utf-8')
    // retorne o conteúdo Markdown da home
    return '# Worklift\n\nDescrição Markdown da home...'
  }
})
```

## Definition of done
- GET / com Accept: text/markdown retorna Content-Type: text/markdown
- Audit P1-MARKDOWN passa

## Notas
- Este check tem impacto prático menor que llms.txt — priorize os outros primeiro.

---
## Instruções finais
- Corrija na ordem listada (critical → high → medium → low).
- Um commit ou PR por tema (robots/sitemap, HTML/headings, JSON-LD) se fizer sentido.
- Ao terminar, liste cada finding e se o critério de pronto foi atendido.
```

---
_Gerado por GEO Score_

Oportunidades

P1-ROBOTS-EXISTS

robots.txt ausente ou inacessível

high

GET https://maggion.com.br/robots.txt → HTTP 403

  • URL testada: https://maggion.com.br/robots.txt

Ação: Publique um robots.txt em /robots.txt referenciando o sitemap e permitindo crawlers de IA.

Ver guia de correção

Passos

  1. Crie o arquivo `public/robots.txt` (ou equivalente na raiz do site servido em `/robots.txt`).
  2. Permita crawlers públicos e bots de IA nas páginas de marketing (home, produto, blog, docs).
  3. Adicione a linha `Sitemap:` apontando para o sitemap canônico (HTTPS).
  4. Faça deploy e valide com `curl -I https://seudominio/robots.txt` → HTTP 200.

robots.txt mínimo

User-agent: *
Allow: /

User-agent: GPTBot
Allow: /

User-agent: ClaudeBot
Allow: /

User-agent: PerplexityBot
Allow: /

Sitemap: https://example.com/sitemap.xml

Pronto quando

  • GET /robots.txt retorna HTTP 200 com conteúdo text/plain
  • Audit P1-ROBOTS-EXISTS passa

P1-SITEMAP

sitemap.xml ausente ou vazio

high

sitemap → HTTP 403, 0 URL(s)

  • Testado: https://maggion.com.br/sitemap.xml

Ação: Publique um sitemap.xml com as URLs canônicas do site.

Ver guia de correção

Passos

  1. Gere um `sitemap.xml` com URLs canônicas HTTPS (home, produto, principais landings, blog).
  2. Configure o CMS/framework para atualizar o sitemap ao publicar páginas.
  3. Referencie o sitemap no `robots.txt` (linha `Sitemap:`).
  4. Submeta o sitemap no Google Search Console (opcional, mas recomendado).

sitemap.xml mínimo

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
    <changefreq>weekly</changefreq>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://example.com/pricing</loc>
  </url>
</urlset>

Pronto quando

  • GET /sitemap.xml → HTTP 200 com ≥1 URL
  • Audit P1-SITEMAP passa

P1-RENDER

Conteúdo depende fortemente de JavaScript

critical

HTML cru = 5.8% do texto renderizado (limiar 20%)

  • Texto visível sem JS: 189 caracteres
  • Texto visível com JS: 3251 caracteres
  • Sem JS (início): "403 Forbidden Forbidden You don't have permission to access / on this server. Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the"
  • Com JS (início): "Pneus Maggion - Seja qual for o seu veículo Institucional Qualidade Diferenciais e vantagens Sustentabilidade Tudo sobre pneu Blog Treinamentos Revendas Assistência Pneus Motocicle"

Ação: Adicione SSR/SSG ou pre-render para crawlers que não executam JS.

Ver guia de correção

Passos

  1. Confirme o stack (Next.js, Nuxt, React SPA, WordPress, Webflow, etc.).
  2. Meça: o HTML inicial da home deve conter texto principal visível sem executar JS.
  3. Escolha uma estratégia: SSR/SSG (preferido), pre-render estático, ou renderização híbrida das rotas públicas.
  4. Garanta que `<title>`, `<h1>` e parágrafos introdutórios existam no HTML servido ao crawler.
  5. Re-teste: ratio texto cru vs renderizado deve ser ≥20%.

Next.js App Router — forçar SSR na página

// app/page.tsx
export const dynamic = 'force-dynamic' // ou use SSG com generateStaticParams

export default function HomePage() {
  return (
    <>
      <h1>Título principal</h1>
      <p>Descrição do produto visível no HTML inicial.</p>
    </>
  )
}

Nuxt 3 — SSG/SSR (default em rotas de marketing)

// pages/index.vue — evite ClientOnly para conteúdo principal
<template>
  <h1>{{ title }}</h1>
  <p>{{ intro }}</p>
</template>

Meta tag fallback (não substitui SSR, só mitiga)

<noscript>
  <h1>Título</h1>
  <p>Resumo do produto para crawlers sem JavaScript.</p>
</noscript>

Pronto quando

  • View Source da home mostra H1 e texto principal sem depender de JS
  • Audit P1-RENDER passa (≥20% do texto renderizado no HTML cru)

P1-STATUS

Status HTTP da home problemático

high

HTTP 403, 0 redirect(s)

  • URL: https://maggion.com.br
  • Status: 403
  • Redirects: 0

Ação: Garanta HTTP 200 na URL canônica com no máximo 1 redirect.

Ver guia de correção

Passos

  1. Acesse a URL canônica do domínio (com HTTPS) e verifique o status HTTP.
  2. Corrija cadeia de redirects: máximo 1 hop até a URL final (idealmente zero).
  3. Resolva 404/5xx na home — verifique DNS, certificado SSL e config do servidor/CDN.
  4. Configure redirect 301 de `http://` e `www` para a versão canônica escolhida.

Pronto quando

  • URL canônica responde HTTP 200
  • ≤1 redirect na cadeia
  • Audit P1-STATUS passa

P1-LLMS-TXT

llms.txt ausente

medium

GET https://maggion.com.br/llms.txt → HTTP 403

  • URL testada: https://maggion.com.br/llms.txt
  • Raiz = mapa; detalhes por página = Markdown linkado (não um arquivo único gigante)
  • Declare rel=alternate / describedby nas páginas importantes

Ação: Crie /llms.txt na raiz (índice leve: o que é, FAQ, links). Se o conteúdo varia por página, publique .md por URL e liste no índice — ver guia do finding.

Ver guia de correção

Passos

  1. Crie `/llms.txt` na raiz (ex.: `public/llms.txt`) — obrigatório para o GEO Score e ponto de entrada dos agentes.
  2. Trate a raiz como **índice leve**: H1 com o nome, blockquote com o que é / para quem, seções curtas (problema, público, FAQ) e uma lista de links Markdown para páginas-chave.
  3. Se o site tem conteúdo distinto por página/seção: **não** cole tudo num único arquivo gigante. Publique Markdown por URL importante (ex.: `/precos.md`, `/produto/x.md`) ou `llms.txt` por escopo (ex.: `/docs/llms.txt`).
  4. No `/llms.txt` raiz, liste esses arquivos: `- [Preços](https://seudominio/precos.md): planos e condições`.
  5. Na HTML de cada página importante, declare descoberta: `<link rel="alternate" type="text/markdown" href="…">` e/ou `<link rel="describedby" href="/llms.txt">` (ou o llms do escopo). Alternativa: header HTTP `Link`.
  6. Mantenha o HTML da página rico (H1, abertura, FAQ) — busca grounded (Perplexity etc.) ainda cita HTML; llms.txt/MD reforçam contexto, não substituem a página.
  7. Faça deploy e valide: `curl https://seudominio/llms.txt` e os `.md` linkados.

llms.txt raiz (índice + links)

# Nome do Produto / Marca

> Descrição direta em 1–2 frases: o que é, para quem, principal benefício.

## O que resolve

- Problema 1
- Problema 2

## Para quem é

- Público A
- Público B

## Perguntas frequentes

### O que é [produto]?
Resposta direta.

## Docs e páginas (Markdown)

- [Home](https://example.com/): visão geral
- [Preços](https://example.com/precos.md): planos e condições
- [Produto X](https://example.com/produtos/x.md): para quem é e diferencial
- [FAQ](https://example.com/faq.md): objeções comuns

## Links HTML

- Site: https://example.com
- Contato: https://example.com/contato

Markdown por página (ex.: /precos.md)

# Preços — Nome do Produto

> Planos para [público]. Sem cartão no trial.

## Planos

- Starter: …
- Pro: …

## Perguntas frequentes

### Tem teste grátis?
Sim, X dias.

Descoberta no HTML / header

<!-- no <head> da página /precos -->
<link rel="alternate" type="text/markdown" href="https://example.com/precos.md" />
<link rel="describedby" href="https://example.com/llms.txt" />

# ou HTTP:
# Link: </precos.md>; rel="alternate"; type="text/markdown", </llms.txt>; rel="describedby"

Pronto quando

  • GET /llms.txt → HTTP 200 com conteúdo Markdown
  • Arquivo tem título H1, pelo menos 2 seções H2 e ≥100 palavras
  • Audit P1-LLMS-TXT passa
  • (Recomendado) Páginas-chave têm .md ou llms de escopo linkados a partir da raiz

P1-AI-TXT

Content Signals (ai.txt) ausente

low

GET https://maggion.com.br/.well-known/ai.txt → HTTP 403

  • URL testada: https://maggion.com.br/.well-known/ai.txt
  • Declarar política aumenta confiança de agentes e pode melhorar indexação em motores que respeitam Content Signals.

Ação: Crie /.well-known/ai.txt declarando sua política de uso por IA (treino, busca, inferência).

Ver guia de correção

Passos

  1. Crie o diretório `public/.well-known/` se não existir.
  2. Crie o arquivo `ai.txt` declarando sua política de uso do conteúdo para IA.
  3. Deploy e valide com `curl https://seudominio/.well-known/ai.txt`.

ai.txt mínimo (permite busca e inferência, nega treino)

# AI Usage Policy — https://seudominio.com
# Baseado no padrão Content Signals (isitagentready.com)

Allow: search
Allow: inference
Disallow: training

ai.txt permissivo (permite tudo)

# AI Usage Policy
Allow: search
Allow: inference
Allow: training

Pronto quando

  • GET /.well-known/ai.txt → HTTP 200
  • Arquivo declara pelo menos Allow: search e Allow: inference
  • Audit P1-AI-TXT passa

P1-MARKDOWN

Servidor não serve Markdown por negociação de conteúdo

low

Requisição com Accept: text/markdown não retornou text/markdown

  • LLMs preferem Markdown limpo a HTML — menos tokens, menos ruído.
  • Para Nuxt/Next.js: adicione um endpoint /api/content ou middleware de content negotiation.
  • Para sites estáticos: serve /llms.txt já cobre a maioria dos casos práticos.

Ação: Configure o servidor/framework para responder com Markdown quando solicitado via Accept: text/markdown.

Ver guia de correção

Passos

  1. Avalie se faz sentido para seu stack — sites estáticos já têm /llms.txt como alternativa mais simples.
  2. Para Nuxt/Next.js: adicione middleware que, quando `Accept: text/markdown` for enviado, sirva uma versão Markdown da página.
  3. Para sites estáticos: garanta que /llms.txt esteja rico — é o equivalente prático.

Nuxt server middleware (server/middleware/markdown.ts)

export default defineEventHandler(async (event) => {
  const accept = getHeader(event, 'accept') ?? ''
  if (!accept.includes('text/markdown')) return

  // Redireciona para versão Markdown equivalente
  const url = getRequestURL(event)
  if (url.pathname === '/') {
    setHeader(event, 'content-type', 'text/markdown; charset=utf-8')
    // retorne o conteúdo Markdown da home
    return '# Worklift\n\nDescrição Markdown da home...'
  }
})

Pronto quando

  • GET / com Accept: text/markdown retorna Content-Type: text/markdown
  • Audit P1-MARKDOWN passa

P1-LINK-HEADERS

Headers HTTP Link (RFC 8288) ausentes

medium

GET https://maggion.com.br/ sem header Link — agentes não descobrem llms.txt, sitemap ou API pelo HTTP

  • Não confundir com <link> no HTML (canonical no <head> não conta). O check lê o header HTTP Link.
  • Formato: Link: </llms.txt>; rel="describedby"; type="text/markdown"
  • Nenhum header Link na resposta da home

Ação: Adicione headers Link na home apontando para /llms.txt, sitemap e, se houver API, /.well-known/api-catalog.

Ver guia de correção

Passos

  1. Confirme que o check é o header HTTP `Link`, não a tag HTML `<link rel="canonical">`.
  2. Na home, envie pelo menos um `Link` apontando para recursos que agentes devem descobrir: `/llms.txt`, `/sitemap.xml`, docs de API se existirem.
  3. Em hosting estático: `_headers` (Netlify/Cloudflare Pages), `nitro.routeRules`, ou config do CDN/nginx.
  4. Valide: `curl -sI https://seudominio.com/ | findstr /i Link` (Windows) ou `curl -sI … | grep -i ^link`.

Headers HTTP (RFC 8288)

Link: </llms.txt>; rel="describedby"; type="text/markdown"
Link: </sitemap.xml>; rel="index"
Link: </.well-known/api-catalog>; rel="api-catalog"

Nuxt — nitro.routeRules

nitro: {
  routeRules: {
    '/': {
      headers: {
        Link: '</llms.txt>; rel="describedby"; type="text/markdown", </sitemap.xml>; rel="index"',
      },
    },
  },
},

Cloudflare Pages / Netlify — public/_headers

/
  Link: </llms.txt>; rel="describedby"; type="text/markdown"
  Link: </sitemap.xml>; rel="index"

Pronto quando

  • GET / inclui header Link com rel de descoberta (describedby, index, api-catalog ou service-doc)
  • Audit P1-LINK-HEADERS passa

P2-JSONLD

JSON-LD ausente

critical

Nenhum bloco JSON-LD em https://maggion.com.br/

  • Busca: <script type="application/ld+json"> — 0 ocorrências
  • URL analisada: https://maggion.com.br/

Ação: Adicione JSON-LD (Organization, Product/SoftwareApplication, FAQPage).

Ver guia de correção

Passos

  1. Adicione pelo menos um bloco `<script type="application/ld+json">` na home (ou layout global).
  2. Inclua `Organization` ou `SoftwareApplication`/`Product` com name, url, description, logo.
  3. Valide JSON (vírgulas, aspas) — JSON inválido é pior que ausência.
  4. Opcional: adicione `WebSite` com `potentialAction` SearchAction se houver busca.

Organization + SoftwareApplication

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Organization",
      "name": "Nome da Marca",
      "url": "https://example.com",
      "logo": "https://example.com/logo.png"
    },
    {
      "@type": "SoftwareApplication",
      "name": "Nome do Produto",
      "applicationCategory": "BusinessApplication",
      "operatingSystem": "Web",
      "description": "O que o produto faz em uma frase.",
      "url": "https://example.com"
    }
  ]
}
</script>

Pronto quando

  • ≥1 bloco JSON-LD válido no HTML da home
  • Audit P2-JSONLD passa

P2-OPENING

Abertura pouco extratível

medium

Primeiros parágrafos não definem o produto claramente

  • Parágrafo 1 (53 chars): "You don't have permission to access / on this server."
  • Parágrafo 2 (111 chars): "Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the request."

Ação: Defina o produto de forma direta nos 2 primeiros parágrafos ("X é uma ferramenta de Y que Z").

Ver guia de correção

Passos

  1. Se a evidência indicar SPA / HTML cru sem <p>: ative SSR/SSG primeiro (P1-RENDER) — reescrever copy no Hero.vue não coloca texto no HTML inicial.
  2. Com HTML populado: reescreva os 2 primeiros parágrafos acima da dobra.
  3. Primeira frase: "[Marca] é [categoria] que [benefício principal]."
  4. Segunda frase: público-alvo ou diferencial concreto.
  5. Evite abrir só com slogans ou CTAs.

Modelo de abertura

<p>Acme é uma plataforma de gestão de tempo para equipes remotas que integra timesheet, aprovações e relatórios em um só lugar.</p>
<p>Indicada para agências e consultorias B2B que cobram por hora e usam Slack no dia a dia.</p>

Pronto quando

  • View Source mostra parágrafo de abertura >50 chars com definição clara
  • Audit P2-OPENING passa

P2-CANONICAL

URL canônica (<link rel="canonical">) ausente

medium

Nenhum <link rel="canonical"> encontrado em https://maggion.com.br/

  • Página analisada: https://maggion.com.br/
  • O canonical evita conteúdo duplicado e ajuda motores de IA a identificar a URL autoritativa.

Ação: Adicione <link rel="canonical" href="https://seudominio.com/"> no <head> de cada página.

Ver guia de correção

Passos

  1. Adicione `<link rel="canonical" href="URL_CANÔNICA">` no `<head>` de cada página.
  2. A URL deve ser absoluta (https://), apontar para a versão preferida da página.
  3. Para Nuxt: use `useHead({ link: [{ rel: "canonical", href: url }] })` ou configure no `nuxt.config`.
  4. Para Next.js: use `<Head><link rel="canonical" href={url} /></Head>` ou metadata API.

HTML direto

<link rel="canonical" href="https://example.com/" />

Nuxt 3 (nuxt.config.js — head global)

head: {
  link: [
    { rel: 'canonical', href: 'https://example.com/' }
  ]
}

Pronto quando

  • <link rel="canonical"> presente no HTML com URL HTTPS válida
  • Audit P2-CANONICAL passa

P2-META

Metadados incompletos

medium

title, meta description ou og:title ausentes ou muito curtos

  • title (13 chars): "403 Forbidden"
  • meta description: (ausente)
  • og:title: (ausente)

Ação: Preencha title, meta description e og:title com texto descritivo (>10 chars).

Ver guia de correção

Passos

  1. Preencha `<title>` único e descritivo (marca + proposta de valor, ~50–60 chars).
  2. Adicione `<meta name="description">` com benefício claro (~120–160 chars).
  3. Configure `<meta property="og:title">` (pode espelhar title ou ser mais marketing).
  4. Opcional: `og:description` e `og:image` para compartilhamento.

Meta tags mínimas

<title>Acme — Gestão de tempo para equipes remotas</title>
<meta name="description" content="Controle horas, aprovações e relatórios. Integração com Slack. Teste grátis.">
<meta property="og:title" content="Acme — Gestão de tempo para equipes remotas">

Pronto quando

  • title, meta description e og:title presentes com >10 caracteres cada
  • Audit P2-META passa

⚠ Precisão do probe não avaliada — ground truth não informado

⚠ Teste em IA não solicitado — apenas análise técnica do site