Qué es el SEO y cómo implementarlo en un producto web
El SEO (Search Engine Optimization) es el conjunto de prácticas que determinan si Google — y otros motores de búsqueda — pueden encontrar, entender y mostrar tu sitio en los resultados de búsqueda. No es magia ni truco: es infraestructura técnica más contenido relevante.
Este artículo documenta los fundamentos que apliqué al construir el SEO de este portfolio, con el código real que se usa en producción.
Por qué importa, incluso para un portfolio
Un portfolio sin SEO es un portfolio que solo existe si alguien ya tiene el link. Con SEO básico:
- Google puede indexarlo y mostrarlo cuando alguien busque tu nombre o habilidades
- Al compartir el link en Slack, WhatsApp o LinkedIn aparece un preview visual (OG image)
- Estableces autoridad técnica — un desarrollador cuyo portfolio tiene SEO bien implementado demuestra que sabe hacerlo
1. Infraestructura de rastreo
Antes de hablar de keywords o contenido, los motores de búsqueda necesitan dos archivos para orientarse.
robots.txt
El archivo /robots.txt le dice a los rastreadores qué pueden y qué no pueden indexar. Sin él, Google asume permiso total pero no tiene referencia al sitemap.
User-agent: *
Allow: /
Sitemap: https://eleddie.com/sitemap.xml
sitemap.xml
El sitemap es un mapa de todas las URLs de tu sitio. En Next.js App Router se genera automáticamente con un archivo TypeScript:
// src/app/sitemap.ts
import type { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: "https://eleddie.com",
lastModified: new Date(),
changeFrequency: "monthly",
priority: 1,
},
];
}
Next.js sirve esto en /sitemap.xml automáticamente.
URL canónica
La URL canónica le dice a Google cuál es la versión "oficial" de una página, evitando penalizaciones por contenido duplicado (útil cuando hay parámetros de query, variantes con/sin www, etc.).
// src/app/layout.tsx
alternates: {
canonical: "https://eleddie.com",
},
2. Meta tags esenciales
Los meta tags viven en el <head> de cada página y controlan cómo Google y los navegadores interpretan el contenido.
title y description
El title es lo que aparece en la pestaña del navegador y en los resultados de Google (SERP). La description es el snippet que acompaña el título en los resultados.
export const metadata: Metadata = {
title: {
default: "elEddie — Developer & Audiovisual Explorer",
template: "%s · elEddie.com",
},
description:
"Edgardo (ElEddie) — Product Engineer y desarrollador full-stack en CDMX. SaaS para industrias médica, financiera y solar. Arte generativo con p5.js.",
};
Reglas prácticas:
- title: máximo 60 caracteres, incluye keyword principal
- description: 120–155 caracteres, lenguaje natural, incluye propuesta de valor
- keywords: relevancia menor hoy, pero útil como señal semántica
viewport y themeColor
export const viewport: Viewport = {
themeColor: "#0A0A0A",
width: "device-width",
initialScale: 1,
};
themeColor colorea la barra de dirección en mobile Chrome y Safari. Detalle pequeño, impacto visual notable.
3. Open Graph y Twitter Card
Open Graph (OG) es el protocolo que controla cómo se ve tu link cuando alguien lo comparte en redes sociales o mensajería. Sin imagen OG, el preview es solo texto — muchas veces ni eso.
openGraph: {
title: "elEddie — Developer & Audiovisual Explorer",
description: "Software, producto y exploración de arte generativo.",
url: "https://eleddie.com",
siteName: "elEddie",
locale: "es_ES",
type: "website",
},
twitter: {
card: "summary_large_image",
title: "elEddie — Developer & Audiovisual Explorer",
description: "Software, producto y arte generativo.",
images: ["/opengraph-image"],
},
OG Image dinámica con next/og
En lugar de crear una imagen estática, Next.js permite generar la OG image en tiempo de build con código:
// src/app/opengraph-image.tsx
import { ImageResponse } from "next/og";
import { readFileSync } from "fs";
import { join } from "path";
export const size = { width: 1200, height: 630 };
export const contentType = "image/png";
export default function OgImage() {
const fontMedium = readFileSync(
join(process.cwd(), "node_modules/@fontsource/ibm-plex-mono/files/ibm-plex-mono-latin-500-normal.woff")
);
return new ImageResponse(
(
<div style={{ background: "#0A0A0A", width: "100%", height: "100%",
display: "flex", flexDirection: "column",
justifyContent: "center", padding: "80px" }}>
<h1 style={{ color: "#EDEDED", fontSize: 80, fontWeight: 500 }}>
elEddie<span style={{ color: "#C6FF00" }}>.com</span>
</h1>
<p style={{ color: "#A3A3A3", fontSize: 28 }}>
Developer & Audiovisual Explorer
</p>
</div>
),
{ ...size, fonts: [{ name: "IBMPlexMono", data: fontMedium, weight: 500 }] }
);
}
Next.js sirve esta imagen en /opengraph-image y la referencia automáticamente en el <head>.
4. Google Search Console
GSC es la herramienta gratuita de Google para monitorear cómo indexa tu sitio. Los pasos mínimos:
Paso 1 — Verificar propiedad
En search.google.com/search-console, agrega tu dominio y elige verificación por HTML meta tag. Copias el código y lo pegas en el metadata de Next.js:
verification: {
google: "tu-codigo-de-verificacion",
},
Hace el deploy y confirmas en GSC. Next.js genera el <meta name="google-site-verification"> automáticamente.
Paso 2 — Enviar sitemap
En GSC → Sitemaps → pega https://tudominio.com/sitemap.xml. Google empieza a rastrear y a reportar errores de indexación, velocidad y cobertura.
Paso 3 — Inspeccionar URL
Con la herramienta de inspección puedes solicitar indexación manual de cualquier URL, ver cómo Google la renderiza y detectar problemas.
5. Datos estructurados JSON-LD
JSON-LD es un formato de datos estructurados basado en schema.org que Google usa para entender el contexto semántico de tu contenido y generar rich results en los SERP.
Para un portfolio, los schemas más relevantes son Person y WebSite:
// src/components/JsonLd.tsx
export default function JsonLd() {
const person = {
"@context": "https://schema.org",
"@type": "Person",
name: "Edgardo Ierr",
alternateName: "ElEddie",
url: "https://eleddie.com",
jobTitle: "Product Engineer & Full-stack Developer",
email: "contacto@eleddie.com",
address: {
"@type": "PostalAddress",
addressLocality: "Ciudad de México",
addressCountry: "MX",
},
sameAs: ["https://github.com/GoatGear"],
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(person) }}
/>
);
}
Para proyectos puedes agregar un ItemList con entradas de tipo SoftwareApplication, permitiendo que Google muestre tus proyectos como resultados enriquecidos.
6. Core Web Vitals — breve
Google usa tres métricas de experiencia de usuario como señal de ranking:
- LCP (Largest Contentful Paint): tiempo que tarda en renderizar el elemento principal. Objetivo: < 2.5 s
- CLS (Cumulative Layout Shift): estabilidad visual — cuánto se mueven los elementos al cargar. Objetivo: < 0.1
- INP (Interaction to Next Paint): tiempo de respuesta a interacciones. Objetivo: < 200 ms
Para un sitio estático en Next.js con SSG, LCP y CLS suelen ser excelentes por defecto. El mayor riesgo es cargar fuentes o imágenes sin dimensiones explícitas.
Buenas prácticas:
- Usar
next/imagepara todas las imágenes (maneja dimensiones, lazy load y formatos modernos) - Cargar solo los pesos de fuente que realmente se usan
- No bloquear el render con scripts síncronos
Checklist de implementación
Infraestructura
✓ robots.txt en /public/robots.txt
✓ sitemap.xml via src/app/sitemap.ts
✓ alternates.canonical en metadata
Meta tags
✓ title con template
✓ description 120-155 chars con keywords
✓ viewport + themeColor
✓ lang="es" en <html>
Social
✓ og:title, og:description, og:url, og:type, og:locale
✓ og:image 1200×630 (estática o dinámica con next/og)
✓ twitter:card summary_large_image con imagen
Datos estructurados
✓ Person schema
✓ WebSite schema
✓ ItemList de proyectos (opcional)
Íconos y PWA
✓ favicon SVG en src/app/icon.svg
✓ apple-icon.png 180×180 en src/app/apple-icon.png
✓ manifest.ts con íconos 192 y 512
Verificación
✓ Google Search Console verificado
✓ Sitemap enviado en GSC
✓ Bing Webmaster Tools (importar desde GSC)
Analítica
✓ Plausible Analytics (privacy-first, sin cookies)
Publicado el 3 de junio de 2026 · elEddie.com