Skill do Especialista SEO para otimização de páginas e sistemas para motores de busca tradicionais e também para otimização para ser citado por LLMs (ChatGPT, Claude, Perplexity, Google AI Overviews). Use quando precisar otimizar meta tags, Open Graph, sitemap, schema markup, Core Web Vitals, performance, imagens, fontes, acessibilidade para SEO, ou qualquer decisão de ranqueamento e citação por motores generativos. Trigger em: "SEO", "meta tags", "Open Graph", "sitemap", "schema markup", "Core Web Vitals", "performance", "LCP", "CLS", "ranking", "canonical", "robots.txt", "GEO", "AEO", "Answer Engine", "LLM citation", "AI Overview", "llms.txt", "generative engine optimization", "answer engine optimization".
60
71%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Optimize this skill with Tessl
npx tessl skill review --optimize ./skills/14-seo-specialist/SKILL.mdO Especialista SEO é responsável por garantir que o sistema e landing pages sejam encontráveis, rápidos e bem ranqueados nos motores de busca.
Esta skill segue GLOBAL.md, policies/execution.md, policies/handoffs.md, policies/quality-gates.md, policies/token-efficiency.md, policies/stack-flexibility.md, policies/evals.md, policies/tool-safety.md e policies/anti-ai-writing.md.
Gate: conteúdo publicado (artigos, meta descriptions, headings) deve passar pelos 29 padrões de policies/anti-ai-writing.md antes de finalizar. Conteúdo com tells de IA penaliza percepção de autenticidade e pode afetar E-E-A-T.
Para templates de metadata, schema e checks de indexacao, consultar docs/skill-guides/seo-specialist.md apenas quando necessario.
src/app/layout.tsx
import type { Metadata } from 'next';
export function generateMetadata({
title,
description,
url,
image,
}: {
title: string;
description: string;
url: string;
image?: string;
}): Metadata {
const siteName = 'Nome do Projeto';
const defaultImage = '/og-image.png';
return {
title: {
default: title,
template: `%s | ${siteName}`,
},
description,
alternates: {
canonical: url,
},
openGraph: {
title,
description,
url,
siteName,
images: [
{
url: image || defaultImage,
width: 1200,
height: 630,
alt: title,
},
],
locale: 'pt_BR',
type: 'website',
},
twitter: {
card: 'summary_large_image',
title,
description,
images: [image || defaultImage],
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
};
}src/components/seo/WebsiteSchema.tsx
export function WebsiteSchema({ url, name }: { url: string; name: string }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'WebSite',
name,
url,
potentialAction: {
'@type': 'SearchAction',
target: `${url}/search?q={search_term_string}`,
'query-input': 'required name=search_term_string',
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}src/components/seo/OrganizationSchema.tsx
export function OrganizationSchema({
name,
url,
logo,
sameAs,
}: {
name: string;
url: string;
logo: string;
sameAs: string[];
}) {
const schema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name,
url,
logo,
sameAs,
contactPoint: {
'@type': 'ContactPoint',
contactType: 'customer service',
availableLanguage: ['Portuguese'],
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}src/components/seo/FAQSchema.tsx
interface FAQItem {
question: string;
answer: string;
}
export function FAQSchema({ items }: { items: FAQItem[] }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: items.map((item) => ({
'@type': 'Question',
name: item.question,
acceptedAnswer: {
'@type': 'Answer',
text: item.answer,
},
})),
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
);
}Métrica Alvo Descrição
─────────────────────────────────────────────────────────────
LCP < 2.5s Largest Contentful Paint — tempo até o maior elemento visível
FID < 100ms First Input Delay — tempo de resposta à primeira interação
CLS < 0.1 Cumulative Layout Shift — estabilidade visual da página
INP < 200ms Interaction to Next Paint — responsividade geral
TTFB < 800ms Time to First Byte — velocidade do servidorTodas as métricas devem estar na zona verde do Google PageSpeed Insights.
next.config.js
const nextConfig = {
images: {
formats: ['image/avif', 'image/webp'],
},
experimental: {
optimizeCss: true,
},
compress: true,
poweredByHeader: false,
};
module.exports = nextConfig;Regras inegociáveis:
next/image — nunca <img> nativowidth e height) em todas as imagenspriority para imagens hero (above the fold)src/components/ui/OptimizedImage.tsx
import Image from 'next/image';
interface OptimizedImageProps {
src: string;
alt: string;
width: number;
height: number;
priority?: boolean;
className?: string;
}
export function OptimizedImage({
src,
alt,
width,
height,
priority = false,
className,
}: OptimizedImageProps) {
return (
<Image
src={src}
alt={alt}
width={width}
height={height}
priority={priority}
loading={priority ? 'eager' : 'lazy'}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className={className}
/>
);
}next/font (self-hosted, zero CLS)font-display: swap obrigatóriosrc/app/layout.tsx
import { Inter } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
});
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="pt-BR" className={inter.variable}>
<body>{children}</body>
</html>
);
}loading="lazy" em imagens e iframes fora da viewportsrc/app/page.tsx
import dynamic from 'next/dynamic';
const FAQ = dynamic(() => import('@/components/sections/FAQ'));
const Testimonials = dynamic(() => import('@/components/sections/Testimonials'));
const Footer = dynamic(() => import('@/components/layout/Footer'));src/components/ThirdPartyScripts.tsx
import Script from 'next/script';
export function ThirdPartyScripts() {
return (
<>
<Script
src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX"
strategy="afterInteractive"
/>
<Script id="gtag-init" strategy="afterInteractive">
{`window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXX');`}
</Script>
</>
);
}Correto Errado
──────────────────────────────────────────
<header> <div class="header">
<nav> <div class="nav">
<main> <div class="main">
<section> <div class="section">
<article> <div class="article">
<aside> <div class="sidebar">
<footer> <div class="footer">
<h1> a <h6> <div class="title">
<figure> + <figcaption> <div class="image-wrapper">
<time datetime=""> <span class="date">
<address> <div class="contact">
<mark> <span class="highlight">Regras:
<h1> por página<main> uma única vez por página<nav> com aria-label quando houver mais de uma navegaçãoVer seção dedicada ## GEO/AEO — Otimização para LLMs e Answer Engines abaixo, com checklist completo de citação por motores generativos (clear claims, quotable headings, FAQ/HowTo schema, E-E-A-T, tabelas, llms.txt).
LLMs como ChatGPT, Claude, Perplexity e Google AI Overviews viraram a primeira camada de descoberta para muitos usuários — eles fazem a pergunta no chat antes de abrir o Google. GEO (Generative Engine Optimization) e AEO (Answer Engine Optimization) cobrem técnicas para tornar o conteúdo extraível, citável e referenciável por esses sistemas. Diferente de SEO clássico (que otimiza ranking em SERP), GEO/AEO otimiza para ser a fonte que o LLM cita textualmente na resposta gerada.
LLMs extraem trechos curtos e atômicos. Estruture o conteúdo para facilitar essa extração:
Além do schema clássico (Website, Organization), priorize tipos que LLMs consomem para grounding:
FAQSchema.tsx — ver seção ## Schema Markup - JSON-LD acima): cada par pergunta/resposta vira candidato a citação direta em AI Overviews.step é extraído individualmente.author (com @type: Person e url para bio), datePublished, dateModified (LLMs ranqueiam por frescor — conteúdo sem dateModified perde relevância em queries que pedem informação atual), publisher, headline, description.const articleSchema = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: title,
author: {
'@type': 'Person',
name: 'Nome do Autor',
url: 'https://site.com/sobre/autor',
},
datePublished: '2025-01-15',
dateModified: '2025-03-20',
publisher: {
'@type': 'Organization',
name: 'Nome da Publicação',
logo: { '@type': 'ImageObject', url: 'https://site.com/logo.png' },
},
};Experience, Expertise, Authoritativeness, Trustworthiness. LLMs filtram fontes por sinais de autoridade explícitos:
<time datetime="2025-03-20">20 de março de 2025</time> visível no corpo, não só no schema.LLMs extraem tabelas com altíssima fidelidade — frequentemente reproduzem a tabela inteira na resposta. Use tabelas sempre que comparar:
Listas com bullets ou numeradas vencem prosa para qualquer enumeração. Se tem mais de 3 itens equivalentes, vire lista.
Arquivo opcional na raiz do site (analogia ao robots.txt), formato markdown, lista o conteúdo canônico e legível por LLMs. Não é padrão oficial mas começou a ser respeitado por crawlers de Anthropic, OpenAI e Perplexity.
public/llms.txt
# Nome do Site
> Descrição breve em 1-2 linhas do que o site oferece.
## Documentação principal
- [Guia de introdução](https://site.com/docs/intro): visão geral em 5 min
- [API Reference](https://site.com/docs/api): endpoints e schemas
- [Tutoriais](https://site.com/tutoriais): passo a passo por caso de uso
## Conteúdo editorial
- [Blog](https://site.com/blog): artigos técnicos atualizados
- [Changelog](https://site.com/changelog): histórico de releases
## Opcional
- [FAQ](https://site.com/faq): perguntas frequentesVersão estendida llms-full.txt pode incluir o conteúdo completo concatenado em markdown plano — útil para sites pequenos onde o LLM pode ingerir tudo.
author, datePublished, dateModified, publisher<time datetime="">llms.txt na raiz do site listando conteúdo canônico/sobre ou /about com missão editorial e biosNão use templates genéricos. Despache skill 17 (image-generator) pra OG card alinhado ao branding:
Tipo: og-card (1200x630) / twitter-card (1200x675)
Texto na imagem: [título do post/página] — tipografia importa
Paleta: [primary], [secondary]
Output path: public/og/ ou public/share/Skill 17 deve usar --model gemini-3-pro (override do default) quando texto na imagem for crítico — gemini-3-pro tem melhor tipografia que grok-imagine ($0.15 vs $0.020, mas vale pra OG card que vai pra produção). Para favicon multi-tamanho e PWA icons, despache skill 36 (Web Asset Generator) a partir do logo gerado.
Meta descriptions: SEO NAO reescreve o copy — apenas otimiza formato, keywords e tamanho. Se o texto precisa mudar substancialmente, devolver pro Copy.
Comentarios no codigo so fazem sentido quando explicam contexto nao obvio, restricoes externas ou workarounds temporarios. O padrao continua sendo codigo claro com nomes descritivos.
7577622
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.