SEO técnico para proyectos pequeños: qué arreglar antes de escribir 100 artículos
Checklist de SEO técnico para blogs y proyectos pequeños: multidioma, canonical, sitemap, schema y errores comunes con Astro.

Cuando lancé oshy.tech, hice lo que hace todo desarrollador que quiere un blog técnico: elegí un stack moderno (Astro), escribí unos cuantos artículos, configuré el deploy y asumí que Google haría el resto. Spoiler: Google no hizo el resto. Meses después descubrí que tenía páginas indexadas que no deberían existir, categorías vacías que diluían la autoridad del sitio, y un sistema multidioma que estaba generando contenido duplicado sin que me diera cuenta.
El SEO técnico para proyectos pequeños es diferente al de sitios grandes. No necesitas un equipo de SEO ni herramientas de pago. Pero sí necesitas entender qué señales está viendo Google cuando rastrea tu sitio, y arreglar los problemas estructurales antes de preocuparte por keywords y backlinks.
El checklist técnico que realmente importa
Hay cientos de checklists de SEO en internet. La mayoría mezclan cosas triviales (“pon un title tag”) con cosas irrelevantes para proyectos pequeños (“optimiza el crawl budget”). Este es el checklist que he construido después de equivocarme con oshy.tech, ordenado por impacto real:
1. Cada URL debe tener un propósito
Parece obvio, pero es donde más fallan los blogs técnicos pequeños. Cada URL que Google indexa es una página que Google evalúa. Si tienes una página de categoría con un solo artículo, Google no ve una sección temática; ve una página casi vacía con un enlace.
Antes de crear categorías o tags, pregúntate: esta página, por sí sola, ofrece valor a alguien que llega directamente? Si la respuesta es no, esa página no debería estar indexada.
2. Canonical tags en todas las páginas
El canonical tag le dice a Google cuál es la versión “principal” de una página. Es especialmente importante si tu blog tiene:
- Versiones con y sin trailing slash (
/blog/posty/blog/post/) - Parámetros de URL que generan variantes (
?page=1,?sort=date) - Contenido multidioma donde las versiones son traducciones
<link rel="canonical" href="https://oshy.tech/es/blog/spring-boot-kotlin-experiencia-real/" />En Astro, el canonical lo puedes generar dinámicamente en tu layout base:
---
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---
<link rel="canonical" href={canonicalURL.href} />El error más común es no ponerlo. El segundo más común es que el canonical apunte a una URL diferente de la que el usuario está viendo, lo que confunde a Google sobre cuál es la versión real.
3. Sitemap correcto y actualizado
El sitemap debería incluir solo las páginas que quieres que Google indexe. Esto parece una tontería, pero el generador automático de Astro (@astrojs/sitemap) incluye por defecto todas las páginas generadas. Si tienes páginas de tags vacíos, categorías con un artículo o páginas de paginación, todo eso va al sitemap.
// astro.config.mjs
import sitemap from "@astrojs/sitemap";
export default defineConfig({
site: "https://oshy.tech",
integrations: [
sitemap({
filter: (page) => {
// Excluir páginas que no aportan valor
if (page.includes("/tags/") && isEmptyTag(page)) return false;
if (page.includes("/category/") && hasFewArticles(page)) return false;
return true;
},
}),
],
});En la práctica, la forma más limpia es no generar esas páginas en primer lugar, pero si ya existen, filtrarlas del sitemap es el primer paso.
4. Robots.txt coherente
El robots.txt y el sitemap deben contar la misma historia. Si bloqueas una sección en robots.txt pero la incluyes en el sitemap, estás enviando señales contradictorias.
User-agent: *
Allow: /
Sitemap: https://oshy.tech/sitemap-index.xmlSi hay secciones que no quieres que se indexen, usa noindex en la meta tag en lugar de bloquear con robots.txt. La diferencia es importante: robots.txt impide el rastreo, pero no la indexación. Si alguien enlaza a una página bloqueada por robots.txt, Google puede indexarla igualmente sin rastrearla, mostrando un resultado sin contenido.
<meta name="robots" content="noindex, follow" />5. Rendimiento básico
Google usa Core Web Vitals como factor de ranking. Para un sitio estático con Astro, esto debería ser casi perfecto por defecto, pero hay errores comunes:
- Imágenes sin dimensiones explícitas (causa layout shift)
- Fuentes web que bloquean el renderizado
- JavaScript innecesario en páginas que no lo necesitan
Con Astro y el componente <Image>, las imágenes se optimizan automáticamente. Pero si usas imágenes en markdown sin el componente, pierdes esa optimización.
Multidioma: donde más se puede complicar
El soporte multidioma es probablemente la decisión técnica más impactante para el SEO de un blog pequeño. Y es donde más errores he cometido con oshy.tech, que tiene contenido en español, inglés y catalán.
Hreflang: la implementación correcta
Los tags hreflang le dicen a Google que varias páginas son la misma pieza de contenido en diferentes idiomas. La implementación correcta requiere que:
- Cada versión de una página apunte a todas las demás versiones, incluida a sí misma
- Las URLs sean absolutas
- Exista un
x-defaultpara la versión principal
<!-- En la página en español -->
<link rel="alternate" hreflang="es" href="https://oshy.tech/es/blog/mi-articulo/" />
<link rel="alternate" hreflang="en" href="https://oshy.tech/en/blog/my-article/" />
<link rel="alternate" hreflang="ca" href="https://oshy.tech/ca/blog/el-meu-article/" />
<link rel="alternate" hreflang="x-default" href="https://oshy.tech/es/blog/mi-articulo/" />En Astro, generar esto requiere un sistema que conecte las versiones de cada artículo entre idiomas. En oshy.tech uso un mappingKey en el frontmatter de cada artículo: todos los artículos que son la misma pieza de contenido comparten el mismo mappingKey, y el layout busca las versiones alternativas para generar los hreflang.
Errores comunes con hreflang
Hreflang no recíproco. Si la versión en español apunta a la inglesa, pero la inglesa no apunta a la española, Google ignora ambos hreflang. Tienen que ser bidireccionales.
URLs incorrectas. Si el hreflang apunta a una URL que redirige, Google lo descarta. La URL debe ser la final, sin redirecciones.
Mezclar canonical y hreflang. El canonical de cada versión debe apuntar a sí misma. Si el canonical de la versión en inglés apunta a la versión en español, le estás diciendo a Google que la versión inglesa es duplicada de la española.
El hreflang es una sugerencia, no una directiva. Google puede ignorarlo si encuentra señales contradictorias. La coherencia entre canonical, hreflang y contenido real es lo que hace que funcione.
El problema del contenido traducido
Una traducción directa de un artículo no es contenido original para Google. Si tu artículo en español es exactamente el mismo que el artículo en inglés, solo que traducido, Google puede tratarlos como contenido similar. Esto no es necesariamente malo si el hreflang está bien implementado, pero en sitios pequeños con poca autoridad, puede diluir las señales.
Mi enfoque actual: escribo el contenido en español (mi idioma principal) y las traducciones son adaptaciones, no traducciones literales. Cambio ejemplos, ajusto referencias culturales y a veces reorganizo secciones. El artículo en inglés no es una copia; es la misma idea adaptada para otra audiencia.
Categorías con pocos artículos: un problema real
Este es el error que más impacto tuvo en oshy.tech. Creé categorías pensando en el futuro: “voy a escribir mucho sobre Kotlin”, “seguro que tengo varios artículos de DevOps”. El problema es que Google no evalúa tu plan editorial. Evalúa lo que existe ahora.
Una categoría con un solo artículo genera una página de listado que tiene:
- Un título (la categoría)
- Un enlace a un artículo
- Posiblemente algo de texto descriptivo
Para Google, eso es thin content. Una página con muy poco valor propio. Si tienes diez categorías así, tienes diez páginas de bajo valor. Y esas páginas se indexan, consumen crawl budget (incluso en sitios pequeños importa) y bajan la percepción general de calidad del sitio.
La solución tiene dos partes:
A corto plazo: marcar como noindex las categorías que tienen menos de cierto número de artículos.
---
const articles = await getArticlesForCategory(category);
const shouldIndex = articles.length >= 3;
---
{!shouldIndex && <meta name="robots" content="noindex, follow" />}A largo plazo: no crear categorías hasta que tengas al menos 3-4 artículos para ellas. Es mejor tener pocas categorías con contenido que muchas categorías vacías. Consolida temas relacionados en una categoría más amplia.
Noindex estratégico: qué páginas no deberían indexarse
No todas las páginas de un blog deben estar en el índice de Google. Para un sitio pequeño, estas páginas suelen ser candidatas a noindex:
- Páginas de tags con pocos artículos. Si el tag “coroutines” tiene un solo artículo, esa página no aporta nada que el artículo por sí solo no aporte.
- Páginas de paginación. La página 2, 3, etc. de un listado raramente aportan valor de búsqueda.
- Categorías con menos de 3 artículos. Como expliqué arriba.
- Páginas de archivo por fecha. Si las tienes, probablemente no aportan.
- Páginas legales estándar. Política de privacidad, aviso legal. Necesarias, pero no necesitan posicionar.
El noindex no elimina la página de tu sitio. Los usuarios pueden seguir navegando a ella. Solo le dice a Google que no la incluya en los resultados de búsqueda.
Schema Article: structured data que funciona
Los datos estructurados (Schema.org) no son un factor de ranking directo, pero ayudan a Google a entender el contenido y pueden generar resultados enriquecidos (rich snippets) que mejoran el CTR.
Para un blog técnico, el schema Article es el más relevante:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "TechArticle",
"headline": "Spring Boot con Kotlin: lo bueno, lo incómodo y lo que nadie te cuenta",
"description": "Experiencia real con Spring Boot y Kotlin...",
"author": {
"@type": "Person",
"name": "Roger Bosch",
"url": "https://oshy.tech/about"
},
"publisher": {
"@type": "Organization",
"name": "oshy.tech",
"url": "https://oshy.tech"
},
"datePublished": "2026-05-18",
"dateModified": "2026-05-18",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://oshy.tech/es/blog/spring-boot-kotlin-experiencia-real/"
},
"inLanguage": "es",
"keywords": ["Spring Boot", "Kotlin", "JPA", "backend"]
}
</script>En Astro, esto se puede generar dinámicamente desde el frontmatter de cada artículo:
---
const { title, description, pubDate, updatedDate, tags } = Astro.props;
const schema = {
"@context": "https://schema.org",
"@type": "TechArticle",
headline: title,
description: description,
datePublished: pubDate,
dateModified: updatedDate || pubDate,
author: {
"@type": "Person",
name: "Roger Bosch",
url: "https://oshy.tech/about",
},
inLanguage: "es",
keywords: tags,
};
---
<script type="application/ld+json" set:html={JSON.stringify(schema)} />Algunos puntos importantes:
- Usa
TechArticleen vez deArticlegenérico si el contenido es técnico. Google lo entiende. dateModifieddebería actualizarse cuando cambias el contenido real, no cada vez que haces un deploy.- El
authordebe ser una persona o entidad identificable, no genérico.
Experiencia real con Astro y estos problemas
Astro es un framework excelente para blogs estáticos. Pero el SEO no viene resuelto “de fábrica”. Estas son las cosas que tuve que resolver manualmente en oshy.tech:
Trailing slashes. Astro puede generar /blog/post o /blog/post/. Si no eliges uno y lo fuerzas, vas a tener ambas versiones y Google puede indexar las dos. En astro.config.mjs:
export default defineConfig({
trailingSlash: "always",
});Sitemap con filtrado. El plugin de sitemap de Astro incluye todo por defecto. Necesité filtrar páginas que no debían indexarse.
Meta tags dinámicas. Cada página necesita title, description, canonical y open graph correctos. En Astro es fácil con layouts, pero hay que hacerlo. No viene solo.
Hreflang dinámico. Con un blog multidioma, generar los hreflang correctamente requiere un sistema de mapping entre artículos. Astro no tiene esto de serie; lo construí con el mappingKey que mencioné antes.
RSS feed por idioma. Un feed RSS único para todos los idiomas es confuso. Generé feeds separados por idioma, cada uno con las URLs correctas.
Qué habría hecho diferente
Si empezara oshy.tech hoy, con lo que sé ahora:
Empezaría con 2-3 categorías máximo, no con ocho. Añadiría categorías solo cuando tuviera 3-4 artículos para cada una.
Implementaría
noindexdinámico desde el primer día para cualquier página de listado con menos de 3 items.Configuraría el multidioma correctamente antes de publicar contenido. Migrar hreflang después es un dolor.
No generaría páginas de tags hasta tener suficiente volumen. Los tags son útiles para navegación interna, pero las páginas de tags en sitios pequeños son thin content.
Validaría con Google Search Console cada semana los primeros meses. La consola te dice qué está indexando Google y qué problemas encuentra. Esa información vale más que cualquier checklist.
El mejor momento para arreglar el SEO técnico es antes de publicar contenido. El segundo mejor momento es ahora. Cada artículo que publicas sobre una base técnica rota es esfuerzo que rinde menos de lo que debería.

