| name | seo-on-page |
| description | Optimiza meta tags, headings, URLs, imágenes, Open Graph y internal linking para SEO on-page en Next.js. Use this skill whenever the user mentions title tags, meta descriptions, generateMetadata, Open Graph, Twitter Cards, OG images, heading hierarchy (H1/H2/H3), URL structure, alt text, anchor text, canonical tags, or social sharing previews — even if they don't explicitly say "SEO on-page". |
SEO On-Page
Cubre meta tags, headings, URLs, imágenes, Open Graph y linking interno. Stack: Next.js 16 App Router, React 19 RSC.
Cuándo invocar este skill
- El usuario pide optimizar
<title> y meta descriptions
- Hay que escribir
generateMetadata para una ruta nueva
- Se está configurando Open Graph / Twitter Cards / OG images
- Se reportan thumbnails feos al compartir links en redes sociales
- El usuario pregunta por estructura de headings (H1/H2/H3)
- Hay dudas sobre URL slugs, anchor text, o internal linking
- Hay que escribir alt text para imágenes
Para Core Web Vitals, sitemap y security headers, usar el skill seo-technical. Para JSON-LD (FAQ, Product, Organization), usar seo-nextjs-implementation.
Title Tags
Patrones por tipo de página
| Tipo | Patrón | Ejemplo |
|---|
| Home | Brand — Tagline | MiApp — BI para ecommerce LATAM |
| Producto | Producto — Categoría | Brand | Nike Air Max — Zapatillas | TiendaX |
| Blog | Título del Post | Brand | Guía de SEO 2026 | MiApp |
| Categoría | Categoría — Descripción | Brand | Zapatillas deportivas | TiendaX |
| Landing | Beneficio Principal — Brand | Aumenta ventas 3x — MiApp |
| Pricing | Precios y Planes | Brand | Precios y Planes | MiApp |
| Feature SaaS | Feature — Qué hace | Brand | Analytics — Métricas en tiempo real | MiApp |
Reglas
- Máx 60 caracteres (Google trunca a ~580px)
- Keyword principal al inicio
- Brand al final separado con
| o —
- Sin duplicados en todo el sitio
- Sin ALL CAPS ni keyword stuffing
Meta Descriptions
Patrones por tipo
| Tipo | Patrón |
|---|
| Producto | Descripción + beneficio + CTA. Precio si aplica. |
| Blog | Resumen del valor + gancho. "Aprendé cómo..." |
| Landing | Beneficio principal + prueba social + CTA. |
| Categoría | Qué encontrarás + cantidad + diferenciador. |
Reglas
- 150-160 caracteres (Google trunca a ~920px)
- Incluir keyword principal naturalmente
- CTA al final: "Descubre cómo", "Empezá gratis", "Ver precios"
- Sin comillas dobles (Google las elimina)
- Única por página
Heading Hierarchy
H1 — Título principal (1 por página, ÚNICO)
H2 — Secciones principales
H3 — Subsecciones
H4 — Detalles (raro, evitar)
Reglas
- UN solo H1 por página
- H1 contiene la keyword principal
- H2s son autosuficientes (passage-level ranking — cada H2 puede aparecer como resultado independiente en Google)
- No saltar niveles (H1 → H3 sin H2)
- Descriptivos, no genéricos. ❌ "Nuestros servicios" → ✅ "Servicios de análisis para ecommerce"
Ejemplo de estructura de blog post
H1: Cómo optimizar SEO para Next.js en 2026
H2: Core Web Vitals — las métricas que importan
H3: LCP — velocidad de carga
H3: INP — interactividad
H3: CLS — estabilidad visual
H2: Structured data con JSON-LD
H3: Product schema
H3: FAQ schema
H2: Optimización para AI search
H3: llms.txt
H3: robots.txt para bots de IA
generateMetadata (Next.js App Router)
Layout-level (template)
import type { Metadata } from "next";
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ?? "https://example.com";
export const metadata: Metadata = {
metadataBase: new URL(baseUrl),
title: {
default: "Brand — Tagline",
template: "%s | Brand",
},
description: "Descripción global del sitio, 150-160 chars.",
openGraph: {
type: "website",
locale: "es_DO",
siteName: "Brand",
images: [{ url: "/og-default.png", width: 1200, height: 630 }],
},
twitter: {
card: "summary_large_image",
creator: "@handle",
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-video-preview": -1,
"max-image-preview": "large",
"max-snippet": -1,
},
},
};
Patrones para páginas estáticas y dinámicas (con datos de DB): references/generate-metadata.md
URL Structure
Reglas
| Regla | Bueno | Malo |
|---|
| Lowercase | /productos/nike-air | /Productos/Nike_Air |
| Hyphens | /guia-seo-2026 | /guia_seo_2026 |
| 3-5 palabras | /blog/optimizar-seo-nextjs | /blog/como-optimizar-el-seo-para-nextjs-en-2026-guia-completa |
| Sin parámetros | /productos/zapatos | /productos?cat=zapatos |
| Sin extensiones | /contacto | /contacto.html |
| Sin trailing slash | /precios | /precios/ |
Trailing slash consistency
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
trailingSlash: false,
};
export default nextConfig;
Image Optimization (next/image)
import Image from "next/image";
<Image src="/hero.webp" alt="..." width={1200} height={630} priority sizes="100vw" />
<Image src={product.image} alt={`${product.name} — vista frontal`}
width={800} height={800} sizes="(max-width: 768px) 100vw, 50vw" />
<Image src={product.thumbnail} alt={product.name}
width={300} height={300} sizes="(max-width: 768px) 50vw, 25vw" />
Reglas de alt text
| Tipo | Alt text | Ejemplo |
|---|
| Producto | Nombre + variante + contexto | Nike Air Max 90 blanco, vista lateral |
| Blog | Descripción del contenido | Gráfico de Core Web Vitals mostrando LCP, INP y CLS |
| Decorativa | Vacío (no omitir el atributo) | alt="" |
| Logo | Nombre de la marca | Logo de MiApp |
| Persona | Nombre + rol | María García, CEO de Curet LLC |
Open Graph + Twitter Cards
OG y Twitter Cards controlan cómo se ve tu sitio cuando alguien comparte un link en redes. Sin OG = thumbnail genérico, ~50% menos CTR en redes sociales.
Specs por plataforma
| Plataforma | Tamaño | Aspect Ratio |
|---|
| Open Graph (Facebook, LinkedIn) | 1200x630 | 1.91:1 |
| Twitter Card | 1200x628 | 1.91:1 |
| LinkedIn | 1200x627 | 1.91:1 |
OG image dinámico con next/og
import { ImageResponse } from "next/og";
export const runtime = "edge";
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const title = searchParams.get("title") ?? "Brand";
return new ImageResponse(
(
<div style={{ /* ... */ }}>
{title}
</div>
),
{ width: 1200, height: 630 }
);
}
Implementación completa de OG dinámico (con descripciones, gradientes, fonts custom) y uso en generateMetadata: references/og-images.md
Internal Linking
Reglas
- 2-5 links internos por página de contenido
- Anchor text descriptivo (NUNCA "click acá", "leer más")
- Linking bidireccional entre páginas relacionadas
- Hub pages (pillar) linkean a spoke pages y viceversa
- Footer con links a páginas principales
Anchor text — bueno vs malo
| Bueno | Malo |
|---|
guía completa de SEO técnico | click acá |
optimizar Core Web Vitals | leer más |
planes y precios de MiApp | ver precios |
Componente RelatedLinks y patrón de links relacionados: references/internal-linking.md
Verificación
| Qué verificar | Herramienta | Frecuencia |
|---|
| Title y meta description | Google Rich Results Test | Post-deploy |
| Open Graph | opengraph.xyz, Facebook Debugger | Post-deploy |
| Twitter Card | Twitter Card Validator | Post-deploy |
| Heading hierarchy | Lighthouse accessibility audit | Semanal |
| Broken internal links | GSC Coverage, Screaming Frog | Mensual |
| Image alt text | Lighthouse accessibility | Semanal |
| URL structure | GSC URL Inspection | Post-cambio |
Referencias técnicas profundas