From d9d4bb885832fb7ddb46e96c133038760fb4a56a Mon Sep 17 00:00:00 2001 From: Emanuel Almeida Date: Thu, 30 Jul 2026 22:39:49 +0100 Subject: [PATCH] wordpress: adiciona skill wp-content-seo-gate --- wordpress/skills/wp-content-seo-gate/SKILL.md | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 wordpress/skills/wp-content-seo-gate/SKILL.md diff --git a/wordpress/skills/wp-content-seo-gate/SKILL.md b/wordpress/skills/wp-content-seo-gate/SKILL.md new file mode 100644 index 0000000..9432a26 --- /dev/null +++ b/wordpress/skills/wp-content-seo-gate/SKILL.md @@ -0,0 +1,110 @@ +--- +name: wp-content-seo-gate +description: "Regras e padrões obrigatórios para geração de conteúdo WordPress com RankMath Pro. INVOCAR AUTOMATICAMENTE quando: (1) escrevendo ou revendo prompts que gerem artigos, posts, descrições de podcast ou qualquer texto para publicar em WordPress, (2) criando, modificando ou auditando sistemas/pipelines/scripts que publicam conteúdo automaticamente em WordPress (publishers, crons, geradores), (3) gerando directamente conteúdo para posts WP. Previne os erros RankMath mais comuns: slug sem focus keyword, título sem número, keyword density baixa, meta description fora do limite." +--- + +# WP Content SEO Gate + +Aplicar ANTES de escrever prompts de geração e ANTES de implementar qualquer sistema que publique em WordPress. + +## Regras Obrigatórias para Prompts de Geração + +Todo o prompt que instruir um LLM a gerar conteúdo WP DEVE incluir estas regras literais: + +| Campo | Regra a incluir no prompt | +|-------|--------------------------| +| `focus_keyword` | 2-5 palavras, foco no benefício/problema, não no nome da ferramenta | +| `slug` | Começar com palavras da focus_keyword (hifenado, sem acentos, ≤75 chars) | +| `rank_math_title` | 50-60 chars, contém focus_keyword E um número (ano corrente ou dado concreto: "47%", "3x") | +| `rank_math_description` | 140-160 chars, focus_keyword nos primeiros 120 chars | +| `content` | focus_keyword nos primeiros 200 chars + ≥2x no corpo + ≥1 H2/H3 com a keyword | +| `image_alt` | 40-100 chars descritivo, contém focus_keyword | +| `secondary_keywords` | 3-5 keywords complementares, cada uma ≥1x no content | + +**Checklist mental no prompt (incluir literalmente):** +- [ ] focus_keyword aparece em: title, rank_math_title, rank_math_description, slug, primeiros 200 chars, ≥1 H2, ≥2x no corpo +- [ ] rank_math_title contém um número (ano ou dado concreto) +- [ ] slug começa com as palavras da focus_keyword +- [ ] ≥600 palavras (RankMath penaliza abaixo deste limite) + +## Padrões Obrigatórios em Publishers/Pipelines + +Todo o sistema que publica em WP via código DEVE implementar estes dois auto-fixes **depois** de receber o JSON do LLM e **antes** de publicar: + +### Auto-fix 1 — Slug sem focus keyword + +```python +def slugify(text: str) -> str: + text = unicodedata.normalize("NFD", text.lower()) + text = "".join(c for c in text if unicodedata.category(c) != "Mn") + text = re.sub(r'[^a-z0-9\s-]', '', text) + return re.sub(r'[-\s]+', '-', text.strip()).rstrip('-') + +def has_keyword_in_slug(slug: str, fk: str) -> bool: + # Match sem stopwords e sem acentos + stopwords = {"a","o","as","os","de","da","do","das","dos","e","em","no","na","nos","nas","para","por","pelo","pela"} + norm = lambda s: " ".join(t for t in slugify(s).replace("-"," ").split() if t not in stopwords) + return norm(fk) in norm(slug) + +# Aplicar após generate_article(): +if not has_keyword_in_slug(article['slug'], article['focus_keyword']): + fk_slug = slugify(article['focus_keyword']) + orig_words = [w for w in article['slug'].split('-') if w not in fk_slug.split('-') and len(w) > 3][:2] + article['slug'] = (fk_slug + ('-' + '-'.join(orig_words) if orig_words else ''))[:75].rstrip('-') +``` + +### Auto-fix 2 — Título sem número (RankMath Title Readability) + +```python +import time, re + +if not re.search(r'\d', article.get('rank_math_title', '')): + year = time.strftime('%Y') + t = article['rank_math_title'].rstrip() + article['rank_math_title'] = (t[:55].rstrip() + f' {year}') if len(t) > 55 else f'{t} {year}' +``` + +## Checklist de Validação Pré-publicação + +Verificar em qualquer publisher antes do `wp post create`: + +- [ ] slug contém focus_keyword (sem acentos, hifenado) +- [ ] rank_math_title tem ≥1 dígito e ≤60 chars +- [ ] rank_math_description entre 140-160 chars e com focus_keyword +- [ ] image_alt contém focus_keyword +- [ ] content ≥600 palavras +- [ ] focus_keyword nos primeiros 200 chars do content +- [ ] ≥1 H2 com a focus_keyword +- [ ] Link externo à fonte (`rel="noopener"`) +- [ ] 1-3 links internos descomplicar.pt no corpo + +## Erros RankMath mais comuns + +| Erro no painel | Causa | Fix | +|----------------|-------|-----| +| "Focus Keyword not found in URL" | LLM gera slug sem a FK | Auto-fix 1 obrigatório | +| "Title doesn't contain a number" | Título sem ano/dado | Auto-fix 2 + instruir LLM | +| "FK not in first 10%" | Lead não inclui a FK | Regra de prompt: FK nos primeiros 200 chars | +| "Keyword density too low/high" | <1% ou >3% | Verificar count antes de publicar | +| SEO Score N/A no dashboard | Post criado via CLI sem Gutenberg | Usar cálculo server-side de `/seo-post` Passo 6 | +| Schema ausente no HTML | Falta `rank_math_schema_*` | Ver `/seo-post` Modo aplicar Passo 3 | + +## PROC Canónico + +**Ler antes de agir:** `Hub/06-Operacoes/Procedimentos/D7-Tecnologia/WordPress/PROC-Conteudo-RankMath.md` (D7-WP-RM-001) + +Este PROC é a fonte única de verdade para: +- Estrutura obrigatória do conteúdo (headings, distribuição FK, elementos por tipo) +- Tabela completa de campos RankMath com valores aceitáveis +- Comandos WP-CLI exactos para aplicar meta, schema e calcular score +- Checklist de validação final (9 pontos) +- Tabela de erros comuns e resolução + +Quando o detalhe de uma regra não está nesta skill, está no PROC. + +## Referências Adicionais + +- `/seo-post` — auditar e corrigir posts **já publicados** via WP-CLI (schema, score, OG, robots) +- `Dev/claude_automations_dev/intelligence-publisher/publisher.py` — implementação de referência dos auto-fixes +- `Dev/claude_automations_dev/intelligence-publisher/prompts/article.md` — prompt de referência para artigos de notícias +- `Hub/05-Projectos/Podcast-Descomplicar-Digital/prompts/generate-wp-description.md` — prompt de referência para posts de podcast