La colección
Cómo nace un producto: un archivo Markdown validado por Zod. El frontmatter, los campos obligatorios y por qué una colección y no .astro sueltos.
Ver la piezaLa guía exacta de cómo crear un producto en este sitio, pieza por pieza: dónde vive, cómo se valida, cómo se ilustra, cómo se tarifa, qué página genera y qué SEO emite.
Mientras la serie Módulos documenta las piezas con las que se arma cada página y Niveles documenta los tipos de página por su profundidad, esta serie documenta el FLUJO de crear un producto. Son seis decisiones encadenadas, cada una con su propia ficha.
Todo descansa en el mismo principio del sistema: una sola fuente de verdad y contenido separado del diseño. Un producto es un archivo Markdown validado por Zod; el catálogo, la ficha y el JSON-LD se generan solos desde esa colección.
Concepto
Una sección (L2) que lista las fichas de producto del sitio y manda a cada detalle. En esta plantilla NO se escribe a mano: cada producto es un archivo Markdown y el grid se genera solo.
Un catálogo es la página que reúne lo que vendes y reparte al visitante hacia la ficha correcta. Aquí cada producto vive como un archivo .md en una colección, con su frontmatter validado por un esquema. La página lee la colección, ordena y pinta una card por producto: agregar o quitar un .md actualiza el catálogo solo, sin tocar la página.
Pensar el catálogo como datos —y no como pantallas dibujadas a mano— es lo que lo mantiene coherente y escalable. Diez productos o mil se ven y se navegan igual; el SEO (la lista, las fichas, el schema) se emite solo; y quien edita el catálogo escribe texto, no código. Esta guía documenta cada parte de ese flujo.
La guía
Las 7 piezas del flujo, cada una como tarjeta: foto, nombre, qué resuelve y sus ideas clave. Entra a cualquiera para verla a fondo, con el mismo molde de las series Módulos y Niveles.
Crear un producto bien hecho son seis decisiones encadenadas: dónde vive (la colección), cómo se ordena (las categorías), cómo entra por los ojos (las imágenes), cómo se tarifa (el precio), qué página genera (la ficha) y qué SEO emite (el schema). Cada tarjeta abre una de ellas.
Es el MISMO card del catálogo —no inventamos un diseño aparte—, porque la coherencia es justo lo que esta serie enseña. Cada pieza tiene su página de detalle con el molde de 10 secciones: qué es, para qué sirve, qué lleva, cómo se ve en móvil, dónde encaja y cómo se construye.
Cómo nace un producto: un archivo Markdown validado por Zod. El frontmatter, los campos obligatorios y por qué una colección y no .astro sueltos.
Ver la piezaEl enum cerrado que organiza el catálogo (equipos · accesorios · general): badges, sincronía site.ts ↔ esquema y enlazado entre fichas.
Ver la piezaLa foto y la galería del producto: ruta obligatoria bajo /images, AVIF ligero, alt con palabra clave y cero saltos de maqueta (CLS).
Ver la piezaPrecio público o «bajo cotización»: el campo opcional, el modelo WhatsApp-first y el Offer honesto, sin cifras inventadas.
Ver la piezaLa página de detalle que se genera sola: ProductLayout (L4), bloques opcionales (specs, usos, FAQ) y la conversión por WhatsApp.
Ver la piezaLos 8 patrones que elevan una ficha básica a L4 premium: hero narrativo, strip de specs, timeline evolutivo, configurador de variantes, traducción operativa de métricas, sidebar de 6 widgets, FAQ voz operador y formulario WhatsApp.
Ver la piezaEl JSON-LD que sale del catálogo: Product + Offer en la ficha, ItemList en el grid, y la regla de un solo emisor por página.
Ver la piezaPor dentro
El índice te dice qué es cada pieza; aquí la abrimos. Mismo formato para todas: qué resuelve, qué decisiones implica y en qué se fija al construirla.
Es el mismo bloque «a fondo» del catálogo del home —información a la izquierda, galería a la derecha, idéntico para cada pieza—. Reusar el patrón es, otra vez, la lección: el sitio se arma con piezas que ya existen.
Aquí está cada pieza del flujo abierta con la misma estructura. Las mismas seis que ves arriba como tarjetas; entra a cualquiera para la versión completa con recetas de código.
La pieza a fondo
Crear un producto en este sitio NO es tocar código: es escribir un archivo Markdown en src/content/productos/. Cada .md es un producto; su frontmatter (título, descripción, categoría, imagen, precio…) se valida contra un esquema Zod .strict() en build-time, que rechaza campos desconocidos y errores de tipo antes de publicar. El catálogo y la ficha de detalle se generan solos a partir de esa colección.
La regla canónica del sistema (D1): toda entidad repetible —producto, servicio, artículo— vive en una Content Collection, nunca hardcodeada en un .astro. Así el contenido (qué dice el producto) y la presentación (cómo se ve) quedan separados: quien edita el catálogo escribe texto en Markdown; quien mantiene el diseño toca el componente, una sola vez, para todos los productos.
La pieza a fondo
Cada producto declara su categoría, y el campo no es texto libre: es un enum CERRADO (equipos · accesorios · general) definido en src/content.config.ts. Es una regla deliberada —un string libre genera, con el tiempo, «Guías» vs «Guias» vs «guía» como tres categorías distintas que fragmentan el SEO y rompen los filtros—. El enum obliga a elegir de una lista fija; Zod rechaza cualquier otro valor en build.
Los slugs del enum deben coincidir con TAXONOMY en site.ts: esa sincronía es la que mantiene el menú, las migas de pan y las rutas alineados con el contenido real. En la card del catálogo la categoría se muestra como badge; entre fichas, el campo relatedProducts/relatedServices (referencias tipadas con reference()) teje el enlazado interno sin URLs escritas a mano.
La pieza a fondo
La imagen de un producto es obligatoria y se valida con una regex: debe ser una ruta absoluta bajo /images/ (Zod rechaza en build cualquier otra cosa). El formato del sitio es AVIF —una foto de catálogo pesa una fracción de un JPG equivalente—, y el texto alternativo (alt) describe lo que se ve con la palabra clave del producto: sirve a quien no puede ver la imagen y da contexto al buscador, nunca es relleno.
Más allá del peso, la imagen se monta para no romper la maqueta: width y height fijos reservan el hueco antes de cargar (cero CLS, cero saltos), y la primera foto del catálogo —la que está sobre el pliegue— carga con prioridad (fetchpriority="high") para cuidar el LCP que mide Lighthouse. La galería opcional (gallery[]) añade vistas extra en la ficha, cada una con su propio alt.
La pieza a fondo
El precio es un campo OPCIONAL y un string libre («Desde $X», «Cotizar»), no un número forzado. La razón es el modelo de negocio del cluster: WhatsApp-first, sin carrito. Si el producto lleva precio público, se muestra; si se omite, el sistema NO inventa una cifra —el CTA pasa a «precio bajo cotización» y abre WhatsApp con un mensaje pre-armado (vía waUrl(), nunca un wa.me escrito a mano)—.
Esa honestidad llega hasta el schema: el Offer de Product se emite «bajo cotización» (UnitPriceSpecification) cuando no hay precio, en lugar de fabricar un valor falso que Google podría penalizar. Es el patrón ideal para catálogos B2B y para productos cuya tarifa depende de volumen, configuración o entrega: pedir el contacto vale más que mostrar un número que no aplica.
La pieza a fondo
La ficha de un producto es su página de detalle (L4) y se genera SOLA: una única ruta dinámica, /productos/[...slug].astro, sirve todas las fichas de la colección. No se edita una página por producto —el título, la imagen, el precio, las FAQs y los relacionados salen del frontmatter—. La estructura vive en ProductLayout, schema-driven y con pocos campos base más bloques opcionales que solo se pintan si traen datos.
Es justo el tipo de página más profunda del catálogo. Lleva un hero con galería + datos clave, una columna de contenido (descripción Markdown, especificaciones, aplicaciones, certificaciones, FAQ) y un sidebar sticky de conversión (cotizar por WhatsApp, llamar). Cada bloque es opcional: un producto sin specs simplemente no muestra esa sección, sin huecos ni placeholders.
La pieza a fondo
La ficha básica informa. La ficha avanzada convence — y lo hace con ocho patrones que transforman una página de detalle en un argumento de venta: hero narrativo (no descripción técnica seca), strip de specs rápidas, apertura de storytelling, timeline evolutivo del modelo, configurador de variantes con cards, traducción operativa de métricas técnicas, sidebar de seis widgets y FAQ en voz de operador con formulario WhatsApp integrado.
Estos patrones no son decoración: resuelven el problema concreto de un comprador técnico que necesita entender rápido, comparar y decidir. El hero narrativo abre con el dato social más poderoso del producto («el caballo de batalla de los grandes departamentos»). El timeline responde «¿en qué generación estoy?». El configurador evita la consulta técnica previa. La traducción operativa de métricas convierte «TPP 42 cal/cm²» en «varios segundos adicionales antes de quemadura de segundo grado». Y la FAQ en voz operador elimina las objeciones que el comprador no articula pero siente.
La pieza a fondo
Del catálogo sale SEO técnico sin escribir JSON-LD a mano. La ficha de producto (L4) emite Product + Offer vía buildSchema('product', …); el grid del catálogo emite CollectionPage + ItemList vía directorySchema. Todo vive centralizado en lib/seo.ts, la única fuente de verdad de los metadatos y el grafo del sitio, alimentada por los mismos datos de la colección y de site.ts.
La regla dura es B3: un único emisor de schema por página. La card de producto NO emite JSON-LD (es presentación pura); el grid emite la lista; la ficha emite el producto. Así no hay @id duplicados ni conflictos entre nodos. Y la regla B4: nunca se fabrica aggregateRating ni reseñas —solo se modelan si son reales y verificables—, porque Google penaliza las reseñas auto-emitidas.
Responsive y móvil
La rejilla no «se encoge»: se reordena. De varias columnas a una sola, con fotos que nunca desbordan y cards que se tocan cómodo.
La vitrina (.showcase) está pensada mobile-first: nace en una columna y crece conforme hay ancho. Nunca al revés: así el caso base (el teléfono) es el más simple y robusto, y el escritorio solo añade.
Lo demás lo resuelve el sistema central: las imágenes AVIF son fluidas y llevan width/height fijos (cero saltos de maqueta), y toda la card es un único enlace con área táctil cómoda. Cada patrón, abajo, con su vista en el teléfono y su receta.
La vitrina es mobile-first: declara una columna y crece con repeat(…, 1fr) en escritorio. Baja a una columna en el teléfono sin tocar la card —el responsive vive en la rejilla—.
/* La vitrina de la guía es mobile-first: 1 → 2 → 3.
Arranca en UNA columna en el teléfono y crece con el ancho disponible.
Nunca al revés. */
.showcase { display: grid; grid-template-columns: 1fr; gap: var(--sp-5); }
@media (min-width: 640px) { .showcase { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .showcase { grid-template-columns: repeat(3, 1fr); } } Cada foto es AVIF con width/height fijos: ocupa el ancho de la card, escala manteniendo su proporción y reserva el hueco antes de cargar (cero CLS). La primera del grid carga con prioridad para cuidar el LCP.
/* tokens.css + mobile.css · la foto de la card, fluida y ligera. */
img, picture, video, canvas, svg { max-width: 100%; } /* nunca más ancha que su caja */
@media (max-width: 768px) {
img, video { height: auto; } /* escala manteniendo la proporción 16:9 */
}
/* La foto es AVIF con width/height fijos → reserva el hueco (cero CLS). */ En el teléfono se toca con el dedo, no con un cursor: toda la card es un único enlace (clic-en-cualquier-lado) con área táctil de 44 px, y lleva un realce de toque suave para confirmar el tap.
/* mobile.css · la card se toca cómodo en el teléfono. */
@media (max-width: 1024px) {
a, button, [role="button"], label {
-webkit-tap-highlight-color: rgba(91, 61, 245, .15); /* feedback al tap */
}
}
@media (max-width: 768px) {
/* chips de subcategoría con altura tappable */
.ccard__sub { min-height: 40px; display: inline-flex; align-items: center; }
} Crea un archivo .md en src/content/productos/ con el frontmatter requerido (título, descripción, categoría e imagen). El grid del catálogo y su ficha individual se generan solos. No se toca ningún .astro.
No. Escribes texto en Markdown; el esquema Zod valida el frontmatter en build-time y la ficha de detalle (L4) se genera sola desde la colección. Contenido y diseño van por separado.
El campo price es opcional. Si se omite, el sistema usa el modelo "bajo cotización" por WhatsApp en lugar de inventar una cifra —y el schema emite un Offer honesto, no un precio falso.
En el enum cerrado PRODUCT_CATEGORIES de src/content.config.ts (equipos · accesorios · general), sincronizado con TAXONOMY en site.ts. Un enum, no texto libre: evita el SEO fragmentado.
Seis, en orden de flujo: la colección, las categorías, las imágenes, el precio, la ficha y el schema. Cada una con su página de detalle y el mismo molde de 10 secciones que Módulos y Niveles.