Complemento del blog · Archivo de etiqueta

El Archivo de etiqueta: conectar el blog por tema

La página que reúne todos los artículos que comparten una etiqueta —/blog/tag/<tag>—. No es una sección del blog: es una capa transversal que cruza las categorías y conecta el contenido por el asunto del que trata.

Esta página no es una ficha técnica: es el complemento entero, abierto y explicado. Qué problema resuelve y por qué la etiqueta gana su lugar junto a la categoría, de qué piezas se compone, cómo se comporta en el teléfono, dónde encaja y, al final, cómo está construida —del criterio de diseño a la línea de código—.

Con un matiz que conviene marcar desde el principio: estas páginas no se escriben a mano. Una sola ruta dinámica —[...tag].astro— deduce de la colección las etiquetas USADAS y genera una página por cada una, con sus artículos. Una sola fuente de verdad; el archivo nunca se desincroniza de las etiquetas reales.

Definición

¿Qué es el archivo de etiqueta?

La página que agrupa todos los artículos marcados con una misma etiqueta. Una capa de organización transversal, paralela a las categorías, que conecta el contenido por tema.

El archivo de etiqueta es la página /blog/tag/<tag> que lista los artículos que comparten una etiqueta —«astro», «seo», «markdown»—. Es una segunda forma de recorrer el blog: no por la sección a la que pertenece cada artículo (su categoría), sino por el asunto puntual del que habla. Vista de lejos parece otra categoría; vista de cerca hace un trabajo distinto.

Y ahí está la distinción que lo define. La categoría es 1:1 y cerrada: cada artículo tiene UNA, elegida de un enum fijo —es su sección—. La etiqueta es N:N y libre: un artículo lleva VARIAS, escritas sin lista predefinida, y la misma etiqueta cruza categorías distintas. Por eso una guía y una novedad pueden compartir #astro aunque vivan en secciones separadas: la etiqueta teje por encima de la categoría.

Función e importancia

¿Para qué sirve?

Hace tres trabajos: ofrece descubrimiento transversal que cruza categorías, teje una red de enlaces internos por tema y se genera sola, una página por etiqueta usada.

Su función es conectar lo que la categoría deja suelto. Un blog ordenado por secciones agrupa bien por área, pero deja sin reunir los artículos que tratan el mismo asunto desde secciones distintas. El archivo de etiqueta cierra ese hueco: junta todo lo de un tema sin importar dónde viva, y le da a quien busca un concepto la vista exacta que necesita.

Y pesa fuera de proporción a su tamaño. Para el lector, es descubrimiento por afinidad temática. Para el SEO, es enlazado interno con anchor text real que reparte autoridad y agrupa contenido relacionado en una URL indexable. Para el mantenimiento, es trabajo cero: las páginas emergen del contenido. Tres efectos, una sola pieza que ni se escribe a mano.

Descubrimiento transversal

La categoría agrupa por sección; la etiqueta cruza esas secciones por un asunto puntual. Un mismo tema —«astro», «schema»— puede vivir en guías y en novedades, y el archivo de etiqueta los reúne sin importar dónde estén. Para quien llegó buscando un concepto, es la vista que la categoría única no puede dar.

Red de enlaces internos por tema

Cada etiqueta teje un nodo que conecta artículos relacionados entre sí y con su archivo. Para el lector, son rutas extra de lectura; para el buscador, enlazado interno con anchor text temático que reparte autoridad y aclara de qué trata cada grupo. La etiqueta es, sobre todo, un conector.

Se genera sola (una por tag usado)

No hay una lista de etiquetas que mantener: getStaticPaths la deduce de los artículos. Publicar un .mdx con tags nuevos crea sus archivos; quitar el último uso de una etiqueta hace desaparecer su página. El sitio refleja siempre las etiquetas reales, sin desincronización posible.

Anatomía

¿Qué lleva el archivo de etiqueta?

Cinco piezas: la ruta dinámica, el cálculo de tags usados, el filtro de artículos, el enlace de entrada y el listado con su SEO de archivo.

Cada pieza cumple un papel claro. La ruta dinámica es la plantilla única; el cálculo deduce qué etiquetas existen; el filtro reparte los artículos —y, como un artículo lleva varias etiquetas, aparece en varios archivos—; el enlace de entrada conecta sidebar y artículo con la página; y el listado la cierra con su rejilla y su SEO. Invisibles arriba (ruta y cálculo), visibles abajo (entrada y listado), todas necesarias.

Abajo, el ejemplo en vivo —réplica anotada de una página de archivo y de la nube de chips que lleva a ella—. Cada punto numerado se desglosa en su tarjeta: qué resuelve y de qué dato sale. A diferencia de una página escrita a mano, aquí todo se deriva de la colección, así que publicar con etiquetas nuevas crea sus archivos solo.

1 /blog/tag/[...tag].astro 2 flatMap(tags) → new Set 3 tags.includes(tag)
1

La ruta dinámica

Un solo archivo —[...tag].astro— produce TODAS las páginas de etiqueta. El parámetro tag es libre (no un enum), así que el slug es la etiqueta tal cual y coincide con el href que ponen el sidebar y el artículo. Una plantilla, N URLs.

Dato src/pages/blog/tag/[...tag].astro

2

El cálculo de tags usados

getStaticPaths recorre los artículos, aplana sus tags y los deduplica con un Set. Así solo se generan páginas de etiquetas que ALGUIEN usa: cero archivos vacíos, cero rutas inventadas. La lista de tags emerge del contenido, no de una lista a mano.

Dato flatMap(p => p.data.tags ?? []) → new Set

3

El filtro de artículos

Cada página recibe como prop los artículos cuyo array de tags INCLUYE esta etiqueta. Como un artículo puede llevar varias, aparece en cada uno de sus archivos a la vez —la relación es N:N—. El filtro es un includes sobre data.tags.

Dato posts.filter(p => (p.data.tags ?? []).includes(tag))

4

El enlace de entrada

A este archivo se llega por dos caminos: la nube de temas del sidebar (los tags más usados como chips) y los chips de tags al pie de cada artículo (ArticleLayout). Ambos apuntan a /blog/tag/<tag>; nadie teclea la URL.

Dato sidebar.temas[] · ArticleLayout tags → /blog/tag/<tag>

5

El listado y el SEO de archivo

El cuerpo es Hero + SectionHeading con el conteo + una rejilla de CategoryCard, una por artículo. El title y la description se arman con la etiqueta, y el breadcrumb cierra en #tag: una página de archivo indexable, no un cul-de-sac.

Dato CategoryCard[] · title/description con <tag>

Variantes

Otros diseños y aplicaciones

La de esta plantilla es una nube de chips por frecuencia hacia cada archivo, pero la entrada y el archivo cambian de cara: lista simple, conteo por tag, tags relacionados, límite o cruce con categoría.

No hay un único modelo: hay una misma idea —agrupar por etiqueta y dar entradas a esos grupos— que cada proyecto ajusta. Un blog sobrio prefiere una lista a la nube; un archivo grande muestra el conteo; una base de conocimiento cruza categoría y etiqueta; una guía larga sugiere etiquetas relacionadas por coaparición.

Abajo, seis variantes —la primera es la del sidebar real, y el resto van de cambios de presentación a extensiones que requieren algo más de lógica—. Cada una con su réplica en vivo y el tipo de proyecto donde rinde mejor.

  • Nube por frecuencia (esta plantilla)

    Blog · Negocio

    La del sidebar: los tags como chips, con el tamaño según cuántas veces se usan. Da de un vistazo los temas dominantes y conduce a cada archivo /blog/tag/<tag>. Es la entrada más reconocible y la que ya arma el sidebar del blog.

  • Lista simple

    Minimal · Pocas etiquetas

    Los mismos tags como una lista vertical, sin escalar el tamaño. Más sobria cuando hay pocas etiquetas o se quiere un orden alfabético claro. Mismos datos, otra presentación; el archivo de destino no cambia.

  • Con conteo por tag

    Archivo grande

    Cada chip muestra el número de artículos —«astro 12»—, como en las categorías. Útil cuando el volumen importa para decidir qué leer. Extensión sencilla: el conteo ya se calcula al deducir los tags usados.

  • Tags relacionados

    Lectura larga · Descubrimiento

    En la página de un archivo, sugerir otras etiquetas que coaparecen con esta en los mismos artículos. Teje la red por afinidad real. Extensión: requiere cruzar los tags de los artículos del archivo actual.

  • Límite de tags mostrados

    Blog grande

    Cuando hay muchas etiquetas, mostrar solo las N más usadas y un «ver todas» hacia un índice completo. Evita una nube infinita en el sidebar. El sidebar ya hace un slice; el índice sería una extensión.

  • Combinación categoría + tag

    Knowledge base

    Filtrar dentro de una categoría por etiqueta —«Guías» + «astro»—, cruzando las dos capas. Da archivos muy específicos. Extensión: rutas o un filtro que combinen ambos ejes de organización.

Responsive y móvil

Cómo se comporta en el teléfono

Dos piezas que adaptar: la nube de chips, que se envuelve sin desbordar, y la rejilla del archivo, que pasa de una a tres columnas. Todo con área táctil cómoda.

En escritorio la nube de etiquetas cabe holgada y la rejilla del archivo muestra tres columnas. En el teléfono no hay ancho para eso, así que los chips usan flex con wrap —saltan de línea sin romperse— y la rejilla baja a una sola columna. Es el mismo comportamiento que ya tienen el sidebar y el listado del blog.

A partir de ahí, tres patrones: la nube que envuelve sus chips, la rejilla que escala 1→2→3 según el ancho, y el cuidado del objetivo táctil para que cada chip mida al menos 44 px y se toque con el dedo sin fallar. Abajo, cada patrón con su vista en el teléfono y su receta.

1 · Nube de chips que se envuelve (default)

La nube es flex-wrap: wrap: si los chips no caben en una línea, saltan a la siguiente sin desbordar la columna. Cada chip lleva white-space: nowrap para no partirse a media palabra. Es lo que hace el sidebar de fábrica.

CSS · nube de chips que envuelve
/* MÓVIL · la nube de chips se envuelve (default).
   El contenedor es flex con wrap: si los tags no caben en
   una línea, saltan a la siguiente sin desbordar la columna. */

.cloud { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.cloud a { white-space: nowrap; }   /* cada chip no se parte a media palabra */

2 · Rejilla 1 → 2 → 3 columnas

El listado de artículos del archivo usa el mismo patrón que el blog: una columna en el teléfono, dos en tableta (640px) y tres en escritorio (1024px). Cada tarjeta es un CategoryCard; el grid hace el resto.

CSS · rejilla responsive del archivo
/* MÓVIL · la rejilla del archivo: 1 → 2 → 3 columnas.
   Una sola columna en el teléfono; dos en tableta; tres en
   escritorio. Mismo patrón que el listado del blog. */

.grid { display: grid; grid-template-columns: 1fr; gap: var(--sp-5); }
@media (min-width: 640px)  { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid { grid-template-columns: repeat(3, 1fr); } }

3 · Área táctil cómoda (≥44 px)

En el teléfono se toca con el dedo: cada chip mide al menos 44 px de alto, el objetivo táctil recomendado, vía padding y min-height. Evita toques fallidos sin que el chip se vea desproporcionado.

CSS · objetivo táctil 44px
/* Área táctil cómoda: cada chip ≥ 44 px de alto en el teléfono.
   Se toca con el dedo, no con un cursor. El padding garantiza el
   objetivo sin que el chip se vea enorme. */

@media (max-width: 768px) {
  .cloud a {
    display: inline-flex; align-items: center;
    min-height: 44px; padding-inline: var(--sp-3);
  }
}

Posición

¿Dónde se coloca?

El archivo es una página propia —/blog/tag/<tag>—, no un bloque dentro de otra. Sus entradas, en cambio, viven en el sidebar y al pie de cada artículo.

Hay que separar dos cosas. El archivo en sí es una página completa, con su Hero, su conteo y su rejilla, generada por la ruta dinámica; ocupa su propia URL dentro del blog. Las ENTRADAS a ese archivo —los enlaces que llevan a él— sí van incrustadas: la nube de temas del sidebar y los chips de tags al pie del artículo (ArticleLayout).

No se repite ni se mete en el chrome global: es contenido del blog, no navegación de todo el sitio. Su relación con el resto es clara: comparte la rejilla y la tarjeta (CategoryCard) con el listado y con el archivo de categoría, y convive con el sidebar —que es, de hecho, una de sus puertas de entrada—.

Piezas cercanas: el archivo de categoría (la otra capa, 1:1 y cerrada), el sidebar (que aloja la nube de temas) y la tarjeta de artículo (la pieza que llena la rejilla).

Implementación

Cómo está construido

Una ruta dinámica ([...tag].astro) cuyo getStaticPaths deduce las etiquetas usadas y genera una página por cada una; un filtro reparte los artículos; el enlace se deriva del tag.

El archivo vive en /blog/tag/[...tag].astro. Su getStaticPaths lee la colección una vez, aplana los tags de todos los artículos y los deduplica con un Set: así nacen exactamente las páginas de las etiquetas usadas, ni una de más. A cada página le pasa, como props, su etiqueta y los artículos que la incluyen —el filtro es un includes sobre data.tags—.

La diferencia con la categoría está en el dato. La categoría es un campo único y cerrado (un enum): se filtra con una igualdad. La etiqueta es un array libre: un artículo lleva varias y por eso aparece en varios archivos, y se filtra con includes. Los enlaces de entrada no se teclean: el sidebar y ArticleLayout derivan /blog/tag/<tag> del propio tag. Cero JavaScript: HTML estático generado en build.

Astro · una página por etiqueta usada (getStaticPaths)
---
// /blog/tag/[...tag].astro · una página por etiqueta USADA, en build.
import { getCollection } from 'astro:content'

export async function getStaticPaths() {
  const posts = (await getCollection('articulos', ({ data }) => !data.draft))
    .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf())

  // Aplana los tags de todos los artículos y deduplica: solo etiquetas usadas.
  const tags = [...new Set(posts.flatMap((p) => p.data.tags ?? []))]

  return tags.map((tag) => ({
    params: { tag },                                          // el slug = la etiqueta
    props: { tag, posts: posts.filter((p) => (p.data.tags ?? []).includes(tag)) },
  }))
}
---
TypeScript · el filtro de artículos (includes vs. la categoría)
// EL FILTRO · los artículos de ESTA etiqueta.
// Un artículo lleva VARIAS etiquetas (N:N), así que aparece
// en cada uno de sus archivos. includes() sobre el array de tags.
const delTag = posts.filter((p) => (p.data.tags ?? []).includes(tag))

// (Comparar con la categoría, que es 1:1 y cerrada:)
//   posts.filter((p) => p.data.category === categoria)
//   → cada artículo tiene UNA categoría; aquí puede tener MUCHAS etiquetas.
Astro · el enlace de entrada (tag → /blog/tag/<tag>)
---
// EL ENLACE DE ENTRADA · el tag se vuelve href, no se teclea.
// (a) Chips al pie del artículo (ArticleLayout):
//     post.data.tags.map(t => /blog/tag/<t>)
// (b) Nube de temas del sidebar:
//     temas[].href ya viene como /blog/tag/<tag>
---

<ul class="tags">
  {(post.data.tags ?? []).map((t) => (
    <li><a href={`/blog/tag/${t}`}>#{t}</a></li>
  ))}
</ul>

En concreto: flatMap((p) => p.data.tags ?? []) aplana los arrays de tags de todos los artículos en una sola lista, y new Set la deduplica. El ?? [] evita tropezar con artículos sin etiquetas. El slug es la etiqueta tal cual, así que coincide con el href que ya generan el sidebar y ArticleLayout: una etiqueta, una URL.

El cuerpo es Hero + SectionHeading con el conteo (posts.length) + una rejilla de CategoryCard, una por artículo. El title y la description se arman con la etiqueta, y el breadcrumb cierra en #tag: cada archivo es una URL indexable con su propio SEO. Todo se genera en build, sin consultas por visita ni JavaScript de cliente.

Buenas prácticas

Qué hacer y qué evitar

La diferencia entre etiquetas que ayudan y etiquetas que estorban cabe en un puñado de hábitos —empezando por no confundirlas con las categorías—.

Ninguno de estos hábitos es capricho: salen de mirar dónde tropieza un blog cuando las etiquetas crecen sin criterio. Un sistema de etiquetas sano usa un conjunto corto y estable, exige que cada una agrupe varios artículos y mantiene la grafía consistente. Uno que estorba inventa una etiqueta por artículo, mezcla sinónimos y confunde la etiqueta con la categoría.

La buena noticia es que casi todo se sostiene solo cuando la disciplina está en el contenido: si los tags se escriben con cuidado, los archivos salen con valor real, porque la lista se deduce de la colección. Abajo, lo que conviene y lo que conviene evitar, enfrentados.

Sí conviene

  • Mantén un conjunto corto y estable de etiquetas, reutilizable entre artículos.
  • Asegura que cada etiqueta agrupe varios artículos: si solo aparece una vez, no merece archivo.
  • Escribe los tags en minúscula y de forma consistente («astro», no «Astro» ni «AstroJS»).
  • Deja que la lista de etiquetas salga del contenido (flatMap + Set), nunca a mano.
  • Pon el conteo en el encabezado y enlaza desde el sidebar y desde el artículo a /blog/tag/<tag>.

Mejor evita

  • No inventes una etiqueta nueva por artículo: llenas el sitio de archivos de un solo elemento.
  • No confundas etiqueta con categoría: la categoría es 1:1 y cerrada; la etiqueta, N:N y libre.
  • No mezcles mayúsculas/sinónimos del mismo tema: parten el archivo en varias páginas flacas.
  • No dejes el archivo sin salidas: cierra con un menú para que no sea un cul-de-sac.
  • No teclees /blog/tag/<tag> a mano en los enlaces: derívalo del tag (sidebar y artículo).
¿Necesitas ayuda?