Módulo del sitio · Categoría a fondo

La Categoría a fondo: el bloque que profundiza

El módulo de dos columnas que amplía UNA categoría justo donde la tarjeta no alcanza: a la izquierda la información detallada —eyebrow, título (H2), párrafos largos, puntos clave y CTA—; a la derecha una galería con una imagen grande y dos pequeñas para ilustrar.

Esta página no es una ficha técnica: es el módulo entero, abierto y explicado. Qué problema resuelve y por qué se ganó su lugar al cierre del catálogo y en cada módulo de la serie, de qué piezas se compone, cómo se comporta en el teléfono, dónde encaja en el armado de la página y, al final, cómo está construido por dentro —del criterio de diseño a la línea de código—.

Con una particularidad que conviene marcar desde el principio: la regla del sitio es dura. Todos los bloques «a fondo» van IDÉNTICOS —info a la izquierda, galería a la derecha—, sin alternar lados ni fondos. La prop reverse del componente existe como antipatrón documentado para no romper proyectos que la necesiten, no para usarse aquí. Coherencia > variedad.

Definición

¿Qué es la categoría a fondo?

El bloque de dos columnas que amplía UNA categoría: a la izquierda la información detallada (eyebrow, título H2, párrafos, puntos clave y CTA); a la derecha una galería con una imagen grande arriba y dos pequeñas debajo.

La categoría a fondo (o «category detail») es el módulo que toma una categoría —un grupo de productos, un servicio, un módulo de la serie— y le da el espacio para explicarse: no solo la frase corta de la tarjeta, sino el cuerpo entero, los datos clave y el contexto visual. No es un duplicado de la tarjeta: es lo que sigue, justo donde la tarjeta no alcanza.

En este proyecto vive en un único componente, CategoryDetail.astro, con una API pequeña (id, eyebrow, title, body, points, cta, gallery, reverse, as). El bloque que estás leyendo ahora mismo, en /modulos/index → «cada módulo, por dentro», es exactamente este componente; y la regla del sitio es estricta —todos los bloques se ven idénticos, info a la izquierda y galería a la derecha, sin variantes que confundan la lectura—.

Función e importancia

¿Para qué sirve?

Hace tres trabajos a la vez: convierte una tarjeta corta en un bloque que vende, junta texto y galería en un mismo movimiento de lectura, y mantiene el ritmo visual del sitio sin pedir CSS por categoría.

Su función es cubrir el hueco entre la tarjeta de catálogo y la página de detalle. La tarjeta abre la puerta —imagen, etiqueta, dos frases—; el bloque a fondo la atraviesa: párrafos largos para vender, puntos clave para escanear y galería para ilustrar. Cuando la categoría se merece más de un vistazo, este es el módulo. La diferencia se mide en visitantes que no se pierden a la página interna sin haber entendido por qué deberían entrar.

Y por eso pesa fuera de proporción a su altura. Para los buscadores, el bloque concentra la promesa de la categoría junto a sus imágenes con alt descriptivo —contenido sustantivo en un solo lugar—; para la accesibilidad, el H2 mantiene la jerarquía y los checks de los puntos son decoración (aria-hidden), no contenido; para el equipo que mantiene el sitio, un solo bloque para todas las categorías significa que ajustar la tipografía o el radio de la imagen se hace en un archivo y se propaga.

Amplía sin abandonar la lista

La vitrina de tarjetas (CategoryCard) entrega el catálogo de un vistazo, pero cada tarjeta solo cabe 1-2 frases. Cuando hace falta vender la categoría —y no solo enseñarla— el bloque a fondo entra justo aquí: párrafos largos, puntos clave y galería sin pedirle al visitante que entre a otra página.

Texto y galería trabajando juntos

La columna izquierda lleva la promesa en palabras; la derecha la refuerza en imágenes. Una imagen grande arriba (4:3) y dos pequeñas debajo dan contexto sin abrumar, y la jerarquía visual es siempre la misma: la información pesa, la galería ilustra. Nunca al revés.

Un solo molde para todas las páginas

En la home cierra el catálogo, en /modulos amplía cada pieza, en /servicios podría ampliar cada servicio. Todos se ven idénticos —info izq · galería der— porque reusan el mismo componente con su misma estructura, sin variantes de presentación que confundan al lector.

Anatomía

¿Qué lleva el bloque?

Cuatro piezas: el eyebrow + título (H2) que abre, el body de párrafos que amplía, los puntos clave con check que resumen, y el CTA + galería que cierran y refuerzan.

Cada pieza cumple un papel claro. El eyebrow con barra de acento ubica de un vistazo («La categoría a fondo», «El módulo a fondo») y el título H2 abre el bloque con la jerarquía correcta. El body es el cuerpo narrativo en 1-3 párrafos; los puntos clave son el resumen en 3-5 bullets con check de color de marca; el CTA es la sola acción del bloque, anclado al final de la columna izquierda; y la galería —una imagen grande y dos pequeñas— ilustra al lado, en proporción y jerarquía pareja.

Abajo, el ejemplo en vivo —réplica anotada a escala del componente—. Cada punto numerado se desglosa en su tarjeta: qué resuelve y de qué prop del componente sale. Y para que el mapeo sea inequívoco, los pines del espécimen apuntan a los mismos elementos del CategoryDetail que aparece en /modulos: lo que ves arriba es exactamente lo que se documenta abajo.

1

Eyebrow + título (H2)

La etiqueta corta con barra de acento («La categoría a fondo», «El servicio a fondo») y el título del bloque, que es un H2 por defecto. La pareja eyebrow + título ubica al visitante en una palabra antes de leer el bloque y mantiene la jerarquía semántica del sitio (H1 del hero → H2 de cada sección a fondo).

Dato props eyebrow · title · as

2

Body (párrafos)

Un array de párrafos que amplía lo que la tarjeta de la vitrina solo deja insinuado: el qué, el por qué y el «con qué se hace». Cada string del array es un <p> propio —el componente itera y los renderiza con margen entre ellos—, así que la página decide la longitud sin tocar el componente.

Dato prop body[]

3

Puntos clave (lista con check)

La lista de bullets con check pintado en color de marca. Son los 3-4 datos sobre los que se quiere dejar caer la mirada —«Entrega 24 h», «Certificado», «Datos desde site.ts»—. Su trabajo es resumir, no repetir el body: títulos cortos, escaneables. Es opcional; sin puntos, la lista no se renderiza.

Dato prop points[]

4

CTA + galería (info y apoyo)

El botón al final de la info («Ver categoría», «Ver módulo») y, en la columna derecha, la galería de apoyo —una imagen grande arriba y dos pequeñas debajo—. El CTA es opcional (los módulos «próximos» se documentan sin enlace); la galería es obligatoria: una imagen principal y un array de thumbs (puede ir vacío).

Dato props cta · gallery (main + thumbs[])

Variantes

Otros diseños y aplicaciones

La de esta plantilla es la canónica (info + puntos + CTA + galería), pero el bloque cambia de cara según lo que la página padre quiera ampliar: catálogo, roadmap, servicio corto, caso editorial, sub-sección.

No hay un único modelo: hay una misma idea —info a la izquierda, galería a la derecha— que cada tipo de bloque ajusta. Un módulo en roadmap omite el CTA (no enlaza a una página inexistente); un servicio corto omite los puntos (la historia es la prueba); un caso editorial deja solo la imagen grande sin thumbs; una sub-sección baja la jerarquía a H3.

Abajo, seis variantes —cinco son configuraciones REALES del componente actual (omitiendo cta, points, thumbs o cambiando as, más la prop reverse documentada como antipatrón), y una es una extensión propuesta que requeriría añadir una prop al componente—. Cada una con su réplica en vivo y el tipo de proyecto donde rinde mejor.

  • Canónica: info + puntos + CTA + galería

    Catálogo · Módulos · Servicios

    La de esta plantilla. Eyebrow + título (H2) + 2 párrafos de body + lista de puntos con check + CTA al final, y a la derecha galería con una imagen grande y dos pequeñas. Lo que se usa en la home (catálogo) y en /modulos (cada módulo a fondo). Configuración real: todas las props llenas.

  • Sin CTA (documentación · módulos próximos)

    Roadmap · Módulos «proximo»

    Misma estructura pero omitiendo la prop cta: la columna de info queda con el body y los puntos sin botón al final. Es la configuración que usa /modulos para los bloques «proximo» —documentan sin enlazar a una página inexistente—. Configuración real: omitir cta. Ya en producción en /modulos.

  • Sin puntos (solo body + CTA)

    Servicios cortos · Productos sin lista

    Cuando la categoría se explica con narrativa pura y no admite bullets útiles, se omiten los puntos: el body y el CTA quedan, la galería al lado. Útil para servicios consultivos o productos cuya promesa es una historia, no una lista. Configuración real: omitir points (o pasar []).

  • Galería de 1 imagen (sin thumbs)

    Editorial · Casos de estudio

    La galería admite un array de thumbs vacío: aparece solo la imagen grande de 4:3, sin la fila de dos pequeñas debajo. Pensado para piezas editoriales (un caso de éxito, un producto con una sola foto fuerte) donde forzar miniaturas debilita el bloque. Configuración real: gallery.thumbs = [].

  • Jerarquía H3 (sub-bloque)

    Listados anidados · Sub-secciones

    Cuando una sección H2 lleva varios bloques a fondo (p. ej. un servicio con sub-servicios), se reusa el componente bajando el título a H3 con la prop as="h3". Mantiene el mismo lenguaje visual sin romper la jerarquía semántica (H2 sección padre → H3 sub-bloque). Configuración real: as="h3".

  • Sobre fondo oscuro (extensión)

    CTA banner · Hero secundario

    Extensión propuesta: misma estructura pero con fondo oscuro y texto claro, para colocar el bloque sobre una sección destacada o un hero secundario. Hoy no existe la prop dark —similar a la de SectionHeading—. Implementarla requeriría derivar los colores del título, el body, los puntos y el border desde la variante.

Responsive y móvil

Cómo se comporta en el teléfono

El bloque no se encoge: cambia de modo. Las dos columnas se apilan info → galería, los thumbs se quedan en pareja, el espaciado entre bloques se comprime y la galería puede plegarse en un acordeón cuando la pila es larga.

En escritorio el bloque vive cómodo como dos columnas (1fr 1fr) con un gap fluido. En el teléfono esas dos columnas no caben sin apretar el texto ni deformar las imágenes, así que el componente colapsa a una sola columna por defecto bajo 768 px —info arriba, galería debajo—. Cero JS: el patrón está en el propio componente, no hace falta media query en la página padre.

A partir de ahí, hay dos detalles que conviene conocer (los thumbs se quedan en 2 columnas para no alargar el bloque y el espaciado entre bloques apilados se comprime en pantallas pequeñas) y una extensión opcional para landings muy largas: envolver la galería en un <details> nativo para que se abra solo cuando el visitante quiere verla. Las cuatro están abajo, cada una con su vista en el teléfono y una receta comentada lista para adaptar.

1 · De dos columnas a una (default)

Es lo que ya hace el componente de fábrica. Bajo 768 px el grid-template-columns pasa de 1fr 1fr a 1fr y la galería cae naturalmente debajo de la info, sin reordenar nada en JS. Cero esfuerzo del consumidor del componente.

CSS · stack 2 → 1 columna (default)
/* MÓVIL · DE DOS COLUMNAS A UNA (lo que ya hace el componente)
   El bloque es grid de 1fr 1fr en escritorio; bajo 768 px se
   colapsa a 1 columna —info arriba, galería debajo— para que el
   texto no se aplaste. Cero JS: el patrón está en el propio
   componente, no hace falta media query en la página padre. */

.cdetail {
  display: grid;
  grid-template-columns: 1fr;       /* móvil: una columna */
  gap: var(--sp-6);
  align-items: center;
}

@media (min-width: 768px) {
  .cdetail {
    grid-template-columns: 1fr 1fr;   /* escritorio: dos columnas */
    gap: clamp(2rem, 5vw, 4rem);      /* gap fluido entre columnas */
  }
}

2 · Los thumbs se quedan en pareja

Excepción a la regla general «todo se apila en móvil»: la galería usa la imagen grande arriba (4:3) y dos pequeñas debajo en una rejilla 1fr 1fr que NO se colapsa. Dos thumbs lado a lado se siguen viendo bien, y apilarlos en columna alargaría demasiado el bloque sin aportar.

CSS · thumbs en 2 columnas (componente)
/* MÓVIL · LOS THUMBS SE QUEDAN EN 2 COLUMNAS (lo que ya hace el componente)
   La galería usa una imagen grande arriba (4:3) y dos pequeñas
   debajo en una rejilla 1fr 1fr. Esa rejilla NO se colapsa en
   móvil: dos thumbs lado a lado se siguen viendo bien, y apilarlos
   en columna alargaría demasiado el bloque. Excepción a la regla
   general «todo se apila en móvil»: aquí la pareja es lo que
   compacta el bloque. */

.cdetail__thumbs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
}
.cdetail__thumb {
  border-radius: var(--radius-md);
  aspect-ratio: 4 / 3;
  box-shadow: var(--shadow-sm);
}

/* La main image también mantiene su 4:3 con border-radius más
   grande —jerarquía visual: grande arriba, pareja debajo—. */
.cdetail__main {
  border-radius: var(--radius-lg);
  aspect-ratio: 4 / 3;
  box-shadow: var(--shadow-md);
}

3 · Espaciado entre bloques comprimido (extensión)

Cuando la pila tiene 4+ bloques (como en /modulos), el clamp() default (2.5rem → 5rem) se siente excesivo en pantallas chicas. Reducir el gap del wrapper .afondo a var(--sp-6) en ≤ 480 px ahorra altura sin sentirse apretado. Extensión local, fuera del componente.

CSS · gap reducido en ≤ 480 px
/* MÓVIL · ESPACIADO COMPRIMIDO ENTRE BLOQUES (extensión)
   Cuando hay 4+ CategoryDetail apilados (p. ej. /modulos),
   el clamp() default (2.5rem → 5rem) se siente excesivo en
   pantallas pequeñas. Esta extensión OPCIONAL lo reduce a
   1.5rem en ≤ 480 px sin tocar el componente. */

.afondo {
  display: grid;
  gap: clamp(2.5rem, 6vw, 5rem);  /* default escritorio */
}

@media (max-width: 480px) {
  .afondo { gap: var(--sp-6); }    /* 1.5rem en móvil */
}

/* Y para que la info no se sienta pegada a la galería del
   bloque anterior en pantallas chicas, el gap interno también
   se reduce un pelín. */
@media (max-width: 480px) {
  .cdetail { gap: var(--sp-4); }
}

4 · Galería colapsable con <details> (extensión)

En landings muy largas (6+ bloques apilados) la galería de 3 imágenes por bloque se siente pesada en móvil. Envolver la galería en un <details> nativo —cerrada por defecto— deja que la info se lea primero. Antipatrón suave: rompe la regla «todos idénticos», úsalo solo cuando la longitud justifique la fricción.

CSS · galería plegable con <details> nativo
/* MÓVIL · GALERÍA COLAPSABLE CON <details> (extensión)
   En vitrinas con 6+ bloques apilados, la galería de 3 imágenes
   por bloque hace que la pantalla se sienta «pesada». Esta
   extensión envuelve la galería en un <details> nativo —cerrada
   por defecto en móvil—, para que la info se lea primero y la
   galería expanda solo si el visitante quiere verla.

   Requiere un cambio en el componente (envolver el div.cdetail__gallery
   en un <details> condicional por viewport o por prop), o un
   wrapper en la página padre. Se documenta como antipatrón
   suave: rompe la regla «todos idénticos» y solo conviene en
   landings muy largas. */

@media (max-width: 640px) {
  details.cdetail__galwrap {
    margin-top: var(--sp-3);
  }
  details.cdetail__galwrap > summary {
    cursor: pointer;
    font-family: var(--font-heading);
    font-weight: var(--weight-semibold);
    font-size: var(--text-sm);
    color: var(--c-primary);
    padding: var(--sp-2) 0;
    list-style: none;          /* oculta el triángulo nativo */
  }
  details.cdetail__galwrap > summary::after {
    content: ' ▾';
    transition: transform var(--transition);
  }
  details.cdetail__galwrap[open] > summary::after { content: ' ▴'; }
}

/* En escritorio, el <details> se ignora y la galería se ve siempre. */
@media (min-width: 641px) {
  details.cdetail__galwrap > summary { display: none; }
  details.cdetail__galwrap[open],
  details.cdetail__galwrap        { display: block; }
}

Posición

¿Dónde se coloca?

Una o varias veces por página, siempre dentro de un .container central, apilados en un wrapper .afondo con gap uniforme. En la home, al cierre del catálogo; en /modulos, uno por cada módulo; en /servicios, podría amplíar cada servicio.

A diferencia de la tarjeta de categoría (N por rejilla) o del hero (uno por página), el bloque a fondo aparece tantas veces como categorías o piezas merezcan amplíarse. En la home cierra el catálogo con 2-3 categorías destacadas; en /modulos hay uno por cada módulo de la serie (15 hoy). El wrapper <code>.afondo</code> reparte la pila con un gap uniforme y la regla canónica del sitio es estricta: nunca alternando lados, nunca alternando fondos.

Vive SIEMPRE dentro del .container central (90 % del ancho, max-width acotado). El bloque respeta el ancho del cuerpo y monta sobre la sección padre (.section o .section--surface) que aporta el padding vertical y el color de fondo. En escritorio, las dos columnas se reparten 1fr 1fr con un gap fluido; en el teléfono, se apilan con info arriba y galería debajo, todo dentro del mismo container.

Implementación

Cómo está construido

Un único componente con API pequeña: id, eyebrow, title, body, points, cta, gallery, reverse, as. Devuelve un <div> con dos columnas (info izq, galería der), un Tag dinámico para el título (h2 por defecto, h3 si se pide) y la galería con width/height fijos para reservar el hueco (sin CLS).

El componente vive en CategoryDetail.astro y expone nueve props a propósito: id (anchor opcional), eyebrow (etiqueta corta con barra), title (obligatorio, el H2), body[] (párrafos), points[] (lista con check, opcional), cta { label, href, external? } (opcional), gallery { main, thumbs[] } (obligatorio), reverse (antipatrón documentado) y as (h2|h3). La regla de uso está cableada en los defaults: as="h2", reverse=false, body=[], points=[]; basta con pasar title y gallery para obtener un bloque válido.

En el sitio, lo más común es alimentarlo desde un map por slug. La página /modulos define AFONDO[slug] con body + points por módulo, mapea MODULOS y por cada uno renderiza un CategoryDetail con el cta condicionado al estado «listo». Misma fórmula podría usarse desde SHOWCASE en la home o desde una Content Collection. Cero JavaScript en el componente: HTML + CSS estático generado en build, imágenes con loading=lazy y decoding=async.

Astro · uso básico (hard-coded, una sola categoría)
---
// USO BÁSICO · pásale las 4 props mínimas (eyebrow, title, body,
// gallery) y listo. La galería siempre lleva una main; los thumbs
// pueden ir vacíos. El componente se encarga del CLS (width/height),
// del lazy de las imágenes y del 2-col → 1-col en móvil.
import CategoryDetail from '@components/CategoryDetail.astro'
---

<section class="section">
  <div class="container">
    <CategoryDetail
      eyebrow="La categoría a fondo"
      title="Cascos de seguridad"
      body={[
        'Cascos homologados para industria pesada, ligeros y con barboquejo ajustable. Stock para entrega 24 h en CDMX y zona metropolitana, garantía de fábrica.',
        'Reposición de piezas, asesoría de uso y capacitación opcional para equipos grandes —el casco se cambia cuando toca, no cuando se ve gastado—.',
      ]}
      points={[
        'Homologación NOM-115-STPS y EN 397',
        'Entrega 24 h en CDMX (stock permanente)',
        'Reposición de barboquejo y suspensión',
        'Capacitación opcional para equipos grandes',
      ]}
      cta={{ label: 'Ver catálogo de cascos', href: '/productos/cascos' }}
      gallery={{
        main:   { src: '/images/showcase/cascos-seguridad-industrial.avif', alt: 'Cascos de seguridad industrial certificados, vista de catálogo' },
        thumbs: [
          { src: '/images/productos/cascos-construccion.avif',  alt: 'Cascos para obra de construcción' },
          { src: '/images/productos/cascos-accesorios.avif',    alt: 'Accesorios para cascos: barboquejo y suspensión' },
        ],
      }}
    />
  </div>
</section>
Astro · data-driven desde AFONDO[slug] (cada módulo a fondo)
---
// DATA-DRIVEN DESDE UN MAP · cómo lo hace /modulos/index.astro.
// Una sola fuente (AFONDO en la página) alimenta los N bloques.
// Recorrer el array MODULOS de site.ts y por cada slug pintar su
// CategoryDetail: agregar un módulo a la SSoT se refleja aquí
// sin tocar el JSX.
import CategoryDetail from '@components/CategoryDetail.astro'
import { MODULOS } from '@config/site'

const AFONDO: Record<string, { body: string[]; points: string[] }> = {
  'topbar':  { body: [/* … */], points: [/* … */] },
  'header':  { body: [/* … */], points: [/* … */] },
  // …un objeto por cada módulo
}
const POOL = ['/images/showcase/a.avif', '/images/productos/b.avif', /* … */]
---

<div class="afondo">
  {MODULOS.map((m, i) => (
    <CategoryDetail
      eyebrow="El módulo a fondo"
      title={m.label}
      body={AFONDO[m.slug].body}
      points={AFONDO[m.slug].points}
      cta={m.estado === 'listo' ? { label: `Ver el módulo ${m.label}`, href: m.href } : undefined}
      gallery={{
        main:   { src: `/images/showcase/${m.slug}.avif`, alt: `Vista del módulo ${m.label}` },
        thumbs: [
          { src: POOL[(i + 1) % POOL.length], alt: `Detalle de ${m.label}` },
          { src: POOL[(i + 2) % POOL.length], alt: `Otro detalle de ${m.label}` },
        ],
      }}
    />
  ))}
</div>

<style>
  /* Regla del sitio: SIN zig-zag, gap uniforme entre bloques. */
  .afondo { display: grid; gap: clamp(2.5rem, 6vw, 5rem); margin-top: var(--sp-6); }
</style>
Astro · reuso desde el catálogo (sin duplicar imagen ni título)
---
// REUSO DESDE EL CATÁLOGO · cómo cerrar la home sin duplicar datos.
// La vitrina (SHOWCASE) ya tiene cada categoría con su image, label,
// blurb y subcategorías. El bloque a fondo reusa label como title e
// image como gallery.main, y solo agrega el body largo y los puntos.
import CategoryDetail from '@components/CategoryDetail.astro'
import { SHOWCASE } from '@config/site'

// El body extendido y los puntos viven aparte (no caben en SHOWCASE,
// que se diseñó para la tarjeta corta). Map por slug:
const EXTENDIDO: Record<string, { body: string[]; points: string[] }> = {
  'cascos':   { body: [/* … */], points: [/* … */] },
  'botas':    { body: [/* … */], points: [/* … */] },
  // …una entrada por categoría destacada
}
---

<div class="afondo">
  {SHOWCASE.filter((c) => EXTENDIDO[c.slug]).map((c) => (
    <CategoryDetail
      eyebrow="La categoría a fondo"
      title={c.label}
      body={EXTENDIDO[c.slug].body}
      points={EXTENDIDO[c.slug].points}
      cta={{ label: `Ver catálogo de ${c.label}`, href: c.href }}
      gallery={{
        main:   { src: c.image, alt: `Catálogo de ${c.label}` },
        thumbs: c.subcategories.slice(0, 2).map((s) => ({
          src: s.image, alt: `Subcategoría ${s.label}`,
        })),
      }}
    />
  ))}
</div>

En concreto: el componente recibe las props, decide la etiqueta del título (const Tag = as) y emite un <div class="cdetail"> con dos sub-divs: .cdetail__info (eyebrow opcional, Tag con el título, los <p> del body, una <ul> de puntos si points.length > 0 y el <a> del CTA si la prop está) y .cdetail__gallery (un <figure> con la main y, si thumbs.length > 0, una rejilla de dos <figure> pequeñas). Las imágenes llevan width="800" height="600" (main) y width="400" height="300" (thumbs) para reservar el hueco y evitar CLS, más loading="lazy" y decoding="async".

La accesibilidad es de fábrica: el contenedor es un <div> estructural, el título es un heading real (<h2> o <h3>), los puntos son una <ul> semántica con icono de check en aria-hidden="true", y la flecha del CTA y la barra del eyebrow también van decorativas. El foco se ve (:focus-visible con outline de marca) y, para quienes prefieren menos animación (prefers-reduced-motion), la única transición —el gap del CTA— se desactiva. Los tokens del proyecto (--c-primary, --radius-lg, --sp-6) son la única fuente de estilo: cambiar el design system cambia todos los bloques a fondo del sitio.

Buenas prácticas

Qué hacer y qué evitar

La diferencia entre una pila de bloques a fondo que se lee con ritmo y una que se siente «hecha por bloques distintos» cabe en un puñado de hábitos —empezando por respetar la regla canónica del sitio: todos idénticos, sin zig-zag—.

Ninguno de estos hábitos es capricho: salen de la regla canónica del proyecto («info izq · galería der, siempre»). El sitio se siente coherente porque cada bloque a fondo nace del mismo componente con la misma disposición, la misma tipografía y el mismo CTA. La única decisión real es la fuente de datos (un map por slug, SHOWCASE, una Content Collection) y qué partes opcionales activar (puntos, CTA, thumbs).

La buena noticia es que casi todo se sostiene solo cuando se respeta el componente: el CLS lo cuidan los width/height de las imágenes, la jerarquía H2 está cableada por la prop as, y el responsive lo resuelve el componente (2 → 1 columna en móvil). Abajo, lo que conviene y lo que conviene evitar, enfrentados.

Sí conviene

  • Mantén SIEMPRE el orden info izq · galería der: la regla dura del sitio es «todos idénticos, sin zig-zag».
  • Reusa CategoryDetail desde una fuente de datos (AFONDO[slug], TAXONOMY o una colección): data-driven, no hard-coded.
  • Escribe el body en 2 párrafos máximo —concepto y por qué—; el detalle fino va en los puntos clave.
  • Limita los puntos clave a 3-5 ideas escaneables («Datos desde site.ts», «Sin correo», «Schema centralizado»).
  • Declara alt descriptivos por imagen (no «imagen1.jpg»); el componente ya añade width/height para evitar CLS.

Mejor evita

  • NO uses la prop reverse para alternar lados en una pila de bloques: rompe la regla de zig-zag del sitio.
  • NO sustituyas el body por la galería: la imagen ilustra, no carga el peso narrativo.
  • NO repitas en los puntos lo que ya dice el body: los puntos son el resumen, no el sub-índice.
  • NO enlaces el CTA si la categoría aún no tiene página propia: omite la prop cta para no generar 404s.
  • NO metas un H1 dentro: el H1 vive en el hero, el componente emite H2 por defecto (H3 con as="h3").

En vivo

El componente, en su uso real

Las galerías de variantes son mockups a escala; este bloque NO. Aquí se renderiza un CategoryDetail real con sus props llenas, idéntico a los que verás en /modulos.

La regla del sitio es estricta —info izq · galería der, sin zig-zag, sin reverse—. Este bloque cierra la página con esa misma disposición canónica, alimentado por el componente real, no por una réplica anotada. Si el componente se rompe, este bloque se rompe a la vista; documentación que se documenta a sí misma.

Las imágenes son las mismas fotos demo del proyecto (AVIF optimizadas, lazy, decoding async). El CTA enlaza al índice de la serie. Reutilizar las fotos del POOL evita inflar el assets de la plantilla: en un sitio real, cada categoría llevaría su propia galería.

La categoría a fondo · ejemplo real

Categoría a fondo, con el propio componente

Este bloque NO es un mockup: es el CategoryDetail real renderizándose, con las props llenas y la misma disposición canónica que el resto del sitio. Si tocas la API del componente, este bloque se rompe en /modulos/category-detail antes que en producción.

La galería usa la misma fórmula del L2 (POOL de fotos demo) para no inflar el repositorio. En un sitio real cada categoría tendría su galería propia, con alt descriptivos por imagen y carga eager solo en la primera (LCP friendly) si el bloque está sobre el pliegue.

  • Disposición canónica: info izquierda · galería derecha (sin reverse)
  • Imágenes con width/height para reservar el hueco (cero CLS)
  • Galería en grid 4:3, thumbs en 2 columnas también en móvil
  • CTA opcional: omítelo cuando la categoría aún no tenga página
Ver todos los módulos
¿Necesitas ayuda?