General
Guía de Creación de Artículos Blog — MUST HAVE
**Versión:** 1.0
name: Guía de Creación de Artículos Blog Postea.la
description: Reglas y checklist para crear artículos SEO sin canibalizmo
type: reference
Guía de Creación de Artículos Blog — MUST HAVE
Versión: 1.0
Fecha: Octubre 2026
Objetivo: Garantizar consistencia, calidad SEO y cero canibalizmo en todos los artículos del blog
1. SEO & ESTRUCTURA
- ✅ Title: 50-70 caracteres, keyword principal al inicio
- ✅ Meta description: 120-160 caracteres, CTA implícito
- ✅ H1: Único por artículo, contiene keyword principal
- ✅ H2: 4-6 máximo, cada uno enfocado en subtema distinto
- ✅ H3: Bajo cada H2, detalles específicos
- ✅ Estructura de headings: MAX 3 niveles (H1 → H2 → H3), NO H4/H5
- ✅ Canonical tag: Presente en head
- ✅ Breadcrumbs: Schema JSON-LD (Inicio > Blog > Artículo)
2. CONTENIDO
- ✅ Largo: 2,400-2,800 palabras por artículo
- ✅ Párrafos: 2-3 oraciones máximo (legibilidad)
- ✅ Keyword density: 1-2% (natural, sin stuffing)
- ✅ Listas con bullets: Máximo 5 items por lista
- ✅ Tablas: Usar solo si aplica comparaciones (filas/columnas claramente definidas)
- ✅ Ejemplos reales: Mínimo 1 caso de uso LATAM específico
- ✅ Call-to-action: 1-2 naturales al final (no invasivos)
- ✅ Párrafo intro: Resume el artículo en 2-3 oraciones
- ✅ Enlaces internos: Máximo 2-3 links a otros artículos (anchor text natural)
3. FAQS (GOOGLE FEATURED SNIPPETS)
- ✅ Cantidad: Mínimo 6, máximo 8 FAQs
- ✅ Pregunta (Q): Redactada como busca la gente (natural, conversacional)
- ✅ Respuesta (A): Corta y directa (1-2 párrafos máximo)
- ✅ Schema FAQPage: Presente en JSON-LD
- ✅ Contenido único: FAQs NO responden cosas de otros artículos (evita canibalizmo)
- ✅ Formato: Cada FAQ resuelve una duda específica del usuario
4. SCHEMA JSON-LD
Todos los artículos deben incluir 3 scripts:
4a. Article Schema
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "[título del artículo]",
"datePublished": "[YYYY-MM-DD]",
"dateModified": "[YYYY-MM-DD]",
"author": {"@type": "Organization", "name": "Postea.la"},
"description": "[meta description]",
"wordCount": [número],
"articleBody": "[resumen del contenido]"
}
4b. BreadcrumbList Schema
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{"@type": "ListItem", "position": 1, "name": "Inicio", "item": "https://postea.la"},
{"@type": "ListItem", "position": 2, "name": "Blog", "item": "https://postea.la/blog"},
{"@type": "ListItem", "position": 3, "name": "[Título artículo]", "item": "[canonical URL]"}
]
}
4c. FAQPage Schema
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "[pregunta 1]",
"acceptedAnswer": {"@type": "Answer", "text": "[respuesta 1]"}
},
...
]
}
5. IMÁGENES (OG TAGS)
- ✅ OG Image: 1200x630px (ratio 1.9:1)
- ✅ Selección: Usar imagen existente de
frontend/src/assets/images/(NO crear nuevas) - ✅ Relevancia: Imagen debe representar el tema del artículo
- ✅ Formato: JPG o WEBP preferente
- ✅ Alt text: Descriptivo, contiene keyword si aplica
- ✅ Registro: Mapear slug → URL en
ARTICLE_OG_IMAGESdict
6. CANIBALIZMO — CRITICAL
ANTES de crear un artículo, verificar:
✅ Keywords NO compitan con artículos existentes
- Revisar
blog_canibalismo_keywords.md - Keyword principal debe ser ÚNICA
- Revisar
✅ Intención de búsqueda DISTINTA
- Ej: "fotos boda invitados" (RECOPILAR) ≠ "álbum digital boda" (COMPARATIVA fotógrafo)
- Ej: "comuniones fotos" (EVENTO) ≠ "fotos privadas evento" (PRIVACIDAD)
✅ Si menciona otro artículo: enlazar con anchor text natural
- NO: "lee también nuestro artículo sobre X"
- SÍ: "el reconocimiento facial te ayuda a..."
✅ Feature único: cada artículo resuelve UN problema específico
- NO mezclar moderación + privacidad + seguridad en un solo artículo
7. CÓDIGO — ESTRUCTURA FUNCIÓN
def article_[slug_corto]():
slug = "[slug-completo]"
canonical = f"{BASE_URL}/{slug}"
title = "[Título 50-70 chars]"
meta_desc = "[Meta description 120-160 chars]"
# Schema Article
schema = {
"@context": "https://schema.org",
"@type": "Article",
"headline": title,
"datePublished": "2026-10-DD",
"dateModified": "2026-10-DD",
"author": {"@type": "Organization", "name": "Postea.la"},
"description": meta_desc,
"wordCount": XXXX,
"articleBody": "[resumen]"
}
# Schema Breadcrumb
breadcrumb = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{"@type": "ListItem", "position": 1, "name": "Postea.la", "item": BASE_URL},
{"@type": "ListItem", "position": 2, "name": "Blog", "item": f"{BASE_URL}/blog"},
{"@type": "ListItem", "position": 3, "name": title, "item": canonical}
]
}
# FAQs (6-8)
faqs = [
("¿Pregunta 1?", "Respuesta 1..."),
("¿Pregunta 2?", "Respuesta 2..."),
# ... máximo 8
]
# Hero section
hero = _hero(
tags=["Tag1", "Tag2", "Tag3"],
h1_line1="Primera línea del H1:",
h1_line2="Segunda línea del H1",
subtitle="Subtítulo/descripción corta",
stats=[("stat1", "label1"), ("stat2", "label2")]
)
# Body (HTML)
body = hero + f"""
<section style="max-width:900px;margin:60px auto;padding:0 20px;">
<h2>Título H2</h2>
<p>Párrafo intro...</p>
<h3>Subtítulo H3</h3>
<p>Contenido...</p>
<h2>Otro H2</h2>
<p>Más contenido...</p>
<h2>Preguntas frecuentes</h2>
<div style="margin-top:8px;">
{{''.join(f'<div class="faq-item"><p class="faq-q">❓ {{q}}</p><p class="faq-a">{{a}}</p></div>' for q, a in faqs)}}
</div>
</section>
""" + _related_articles(slug)
# Schema FAQPage
faq_schema = {
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [{"@type": "Question", "name": q, "acceptedAnswer": {"@type": "Answer", "text": a}} for q, a in faqs]
}
return html_page(title, meta_desc, canonical,
_json.dumps(schema, ensure_ascii=False),
_json.dumps(breadcrumb, ensure_ascii=False),
body, _json.dumps(faq_schema, ensure_ascii=False),
og_image=ARTICLE_OG_IMAGES.get(slug))
8. FORMATO & ESTILOS
- ✅ CSS: Mismo que artículos existentes (variables de paleta)
- ✅ Paleta de colores:
- Dorado:
#c9a96e - Crema:
#f9f7f4 - Gris oscuro:
#333/#555
- Dorado:
- ✅ Tipografía:
- Títulos (H1/H2):
Playfair Displayserif - Body:
Intersans-serif
- Títulos (H1/H2):
- ✅ Estilos: Inline styles, NO clases CSS, NO
::ng-deep - ✅ Bootstrap: NO usar clases Bootstrap
- ✅ Consistencia: Márgenes, paddings, tamaños de fuente idénticos a artículos existentes
9. GIT WORKFLOW
Commit 1: Crear funciones
git add frontend/scripts/blog-generator.py
git commit -m "feat: create 3 article functions (slug1, slug2, slug3)"
Commit 2: Registrar imágenes OG
git add frontend/scripts/blog-generator.py
git commit -m "feat: add OG images mapping for 3 articles"
Commit 3: Registrar en ARTICLES array
git add frontend/scripts/blog-generator.py
git commit -m "feat: register 3 articles in ARTICLES array (Lote X)"
Generate & Deploy
python3 frontend/scripts/blog-generator.py frontend/dist/postea-la/browser
./deploy-frontend.sh
10. VALIDACIÓN FINAL — CHECKLIST
- ✅ Compilación sin errores (
python3 blog-generator.pyexitoso) - ✅ Archivos .html generados (tamaño 25-30KB cada uno)
- ✅ Schema JSON válido (sin syntax errors, se puede parsear)
- ✅ Sitemap actualizado con URLs nuevas
- ✅ URLs accesibles en producción (
https://postea.la/[slug]) - ✅ Title visible en browser tab
- ✅ H1 visible en pantalla
- ✅ FAQs renderizadas correctamente
- ✅ OG Image se carga sin errores 404
- ✅ Canonical tag correcto
- ✅ NO hay canibalizmo con artículos existentes
CHECKLIST RÁPIDO ANTES DE CREAR
[ ] ¿Keyword principal es ÚNICA? (revisar blog_canibalismo_keywords.md)
[ ] ¿Intención de búsqueda es DISTINTA a otros artículos?
[ ] ¿Title 50-70 chars? ¿Meta desc 120-160 chars?
[ ] ¿H1 único? ¿H2 entre 4-6?
[ ] ¿6-8 FAQs naturales?
[ ] ¿2,400-2,800 palabras?
[ ] ¿Mínimo 1 caso LATAM real?
[ ] ¿OG Image 1200x630px existe?
[ ] ¿Funciones → OG_IMAGES → ARTICLES (3 commits)?
[ ] ¿Deploy exitoso?
[ ] ¿URL accesible en producción?
Última actualización: Octubre 2026
Responsable: César Estrada / Melissa Vásquez