Guía · Topbar

Barra utilitaria superior (la franja por encima del menú). Cada punto se alimenta de src/config/site.ts (fuente única); no se escribe a mano. Esto es lo que va en cada lugar:

  1. 1

    Propuesta principal

    Lo primero que se lee: una frase corta que posiciona la marca. El logotipo NO va aquí — va en el Header, justo debajo.

    Dato SITE.tagline

  2. 2

    Horario

    Señal de disponibilidad y confianza. Se oculta en móvil para priorizar el teléfono y WhatsApp.

    Dato CONTACT.schedule.display

  3. 3

    Teléfono

    Contacto directo con clic-para-llamar. El enlace tel: lo construye telUrl(), no se escribe a mano.

    Dato CONTACT.phone · telUrl()

  4. 4

    WhatsApp

    CTA principal de contacto. El enlace SIEMPRE se arma con waUrl(); el mensaje precargado sale de WA_MESSAGES.

    Dato waUrl(WA_MESSAGES.cotizar)

Edita en src/components/TopBar.astro · src/config/site.ts

Guía · Header

Barra de navegación principal (logotipo + menú), bajo el topbar. Todo el menú —escritorio, paneles y móvil— se genera desde NAV en src/config/site.ts (fuente única); no se escribe a mano. Esto es lo que va en cada lugar:

  1. 1

    Logotipo

    La marca, a la izquierda, enlazando a la home. Es el ancla de identidad y el «volver al inicio» que todos esperan. Aquí SÍ va el logo (en el topbar no).

    Dato SITE.brand · SITE.name

  2. 2

    Navegación

    Las secciones del sitio. No se hardcodea ningún enlace: se itera NAV, la misma fuente para escritorio y móvil. En móvil colapsa en el menú ☰.

    Dato NAV

  3. 3

    Paneles (mega / dropdown)

    Las secciones con hijos despliegan un panel al pasar el cursor o con el teclado; su contenido sale de la taxonomía, no de una lista aparte.

    Dato NAV[].panel · items

  4. 4

    CTA · Cotizar

    El botón de conversión a WhatsApp, siempre visible a la derecha. El enlace se arma con waUrl(); el mensaje precargado sale de WA_MESSAGES.

    Dato waUrl(WA_MESSAGES.cotizacion)

Edita en src/components/Header.astro · src/config/site.ts

Guía · Migas de pan

La ruta que muestra dónde está el visitante dentro de la jerarquía del sitio, justo debajo del header. Sirve para dos cosas a la vez: orientar y dejar volver a cualquier nivel superior, y alimentar el BreadcrumbList de schema.org que el buscador usa para mostrar la ruta en sus resultados. Cada página define su ruta una sola vez con la prop breadcrumbs; el JSON-LD lo emite buildSchema (no este componente, para no duplicarlo). Esto es cada eslabón:

  1. 1

    Raíz (Inicio)

    El primer eslabón: siempre enlaza a la home. Es el punto de partida de la ruta y el «volver al inicio» que todos esperan de la jerarquía.

    Dato items[0] · href '/'

  2. 2

    Eslabón intermedio

    Cada nivel ancestro entre la home y la página actual (categoría, subcategoría). Son enlaces: dejan saltar a cualquier nivel superior.

    Dato items[].href

  3. 3

    Separador

    El icono (›) entre eslabones. Es decorativo —va con aria-hidden— y solo marca la dirección de la jerarquía; nunca es un enlace.

    Dato SVG · aria-hidden

  4. 4

    Página actual

    El último eslabón: la página donde estás. No enlaza (ya estás ahí) y se marca con aria-current="page" para los lectores de pantalla.

    Dato item sin href · aria-current

Edita en src/components/Breadcrumbs.astro · prop breadcrumbs de cada página

general

Construir un sitio Astro+Markdown: 12 módulos

Tesis técnica: cómo se construye un sitio profesional con Astro y Markdown encadenando 12 módulos como referencia industrial. Mapa, decisiones y enlaces.

Construir un sitio Astro+Markdown: 12 módulos

Un sitio profesional no se arma copiando un theme y rellenando huecos. Se arma como un sistema: doce piezas que se enganchan en un orden conocido, cada una con un trabajo claro, ninguna duplicando el trabajo de otra. Esta tesis presenta ese sistema —los doce módulos que sostienen un sitio Astro+Markdown listo para producción— y enlaza con los 24 artículos que cubren cada módulo en profundidad. Es el ancla de la biblioteca del sitio: si llegaste a un artículo individual, este es el mapa que te dice dónde encaja. Si entras por aquí, los enlaces te llevan al detalle. Está escrita para developers que ya pasaron la curva inicial de Astro y quieren entender por qué este sistema y no otro.

Contexto

Astro 6 cambió las reglas. El framework optimiza para sitios estáticos, deja JavaScript opcional por componente (no por página) y trata el contenido como ciudadano de primera con Content Collections + Zod. Lo que antes era una decisión arquitectónica costosa —SSG vs SSR, headless CMS vs Markdown, validación de schema vs confianza en el editor— ahora es una elección de fricción mínima. La consecuencia es que un sitio profesional puede vivir entero en Markdown con glob loaders y compilarse a HTML estático que se sirve desde Cloudflare Pages sin servidor propio. Cero base de datos, cero panel admin, cero costo recurrente más allá del dominio.

Lo que no cambió es el problema editorial. Un sitio de cliente necesita los mismos doce bloques: barra superior con datos de contacto, header con menú, hero con propuesta, migas de pan, menús internos, encabezados de sección, tarjetas de categoría y de producto/servicio, bloques a fondo, FAQ, reseñas, formularios de contacto, banners de cierre y un footer con NAP. Cada bloque tiene mil variantes en la web; este sistema fija una decisión por pieza, la documenta y la repite. La consistencia no es cosmética: es lo que permite que el próximo sitio se arme en dos semanas en vez de dos meses.

El tercer eje es la regla de oro del repo: un único emisor por entidad (regla B3). El JSON-LD lo emite el layout, no los componentes. El BreadcrumbList, el Product, el FAQPage, el Organization viven cada uno en exactamente un lugar de la página. Esta regla, aplicada a doce módulos, produce páginas con schema válido sin duplicados y sin que ningún componente hijo tenga que enterarse de SEO. La explicación detallada vive en cada artículo de módulo; aquí se enuncia como el pegamento que hace que doce piezas independientes formen un sistema coherente.

El sistema de 12 módulos

El flujo del visitante recorre los doce en un orden previsible. La barra superior fija la marca, el header navega, el hero presenta, las migas ubican, el menú de sección reparte, los headings articulan, las cards listan, los detalles educan, las FAQ resuelven, las reseñas legitiman, el footer cierra, los formularios y CTAs convierten. Cada módulo es independiente —se puede usar sin los otros— pero el ensamble completo es lo que produce una página que se siente armada.

#MóduloTrabajoPágina L3
1BreadcrumbsOrientar y enlazar la jerarquía/modulos/breadcrumbs
2Section menuAnclas internas + cierre data-driven/modulos/section-menu
3Section headingArticular secciones con jerarquía/modulos/section-heading
4Category cardVitrina escalable desde collection/modulos/category-card
5Category detailBloques a fondo info + galería/modulos/category-detail
6Product cardCatálogo con frontmatter Markdown/modulos/product-card
7Service cardServicios con CTA dual ficha/WhatsApp/modulos/service-card
8FAQAcordeón nativo + FAQPage schema/modulos/faq
9ReviewReseñas honestas con schema gateado/modulos/review
10FooterActivo SEO global + NAP + Organization/modulos/footer
11Contact formForm a11y WCAG + honeypot + serverless/modulos/contact-form
12CTA bannerCierre honesto con tracking respetuoso/modulos/cta-banner

La biblioteca de 24 artículos

Cada módulo tiene dos artículos: uno técnico-mecánico (cómo hacerlo) y uno estratégico-ético (cuándo, por qué y qué evitar). Veinticuatro artículos que se leen en cualquier orden y se cross-linkean entre sí. El orden recomendado es el del flujo del visitante —empezar por breadcrumbs y terminar por CTA banner—, pero cada par es autocontenido y se puede consumir como solución a un problema concreto.

Módulos de navegación (1–3)

El primer bloque arma cómo se mueve el visitante dentro del sitio.

Módulos de catálogo (4–7)

El segundo bloque arma cómo se presenta la oferta. El patrón es siempre el mismo: la collection Markdown declara los datos, el componente pinta una pieza, la página padre ensambla el grid.

Módulos de confianza (8–9)

El tercer bloque trabaja la legitimidad de la oferta. Aquí es donde la disciplina ética del repo se vuelve decisión técnica: las FAQs sirven preguntas reales y las reseñas se gatean para no falsear schema.

Módulos de cierre (10–12)

El cuarto bloque cierra: footer global, formularios serverless y CTAs sin trampas. Es la parte que más se descuida en la web mexicana y la que más diferencia un sitio profesional del resto.

Decisiones que atraviesan todo el sistema

Cuatro decisiones técnicas se aplican a los doce módulos. Conviene tenerlas presentes al leer cualquier artículo, porque cada uno las da por supuestas.

Content Collections como única fuente de datos repetibles. Todo lo que aparece más de una vez en el sitio —productos, servicios, artículos, zonas, casos— vive en src/content/ con schema Zod estricto. La página padre lee con getCollection(), filtra drafts, ordena y mapea a su componente. Cero arrays hardcoded en .astro. La razón es operativa, no purista: agregar el sexto servicio cuesta un archivo Markdown, no una tarde de buscar y reemplazar. Los artículos de catálogo (4–7) explican el patrón en detalle.

Un único emisor por entidad de schema (regla B3). El JSON-LD lo arma buildSchema() una vez por página en <head>, desde el layout. Los componentes hijos no emiten <script type="application/ld+json">. Esto evita warnings de Search Console por entidades duplicadas y mantiene la lógica de schema en un solo archivo (src/lib/seo.ts). Los artículos 2, 12, 15 y 19 cubren la regla aplicada a breadcrumbs, productos, FAQ y Organization.

Honestidad antes que rich results (regla B4). El repo no auto-emite reseñas, no falsea AggregateRating y no marca como Service algo que no es un servicio. Cuando los datos no existen, el schema no se emite. La razón es de fondo: Google penaliza datos estructurados inventados y la confianza del visitante se daña más por una falsa reseña descubierta que por la ausencia de estrellas. Los artículos 17 y 18 desarrollan esta posición con casos.

Mobile-first con tokens y breakpoints fijos. El responsive vive en mobile.css con breakpoints 1024/768/640/480/380. Los componentes nuevos se prueban primero en móvil real, no en el devtools. El container es fluido (90% → 100% en ≤768), los CTAs son full-width en pantallas chicas, los inputs llevan 16px para no zumbar en iOS. Los artículos de catálogo (8, 20) y formularios (21) cubren este sistema.

Cómo se enganchan los módulos en una página real

Una página de servicio individual (/servicios/instalacion) usa nueve de los doce módulos en orden: breadcrumbs (/servicios/instalacion) → hero del servicio → section-menu interno (anclas a precios, FAQs, contacto) → section-heading articulando cada subsección → product-card o service-card relacionada → category-detail con bloques a fondo → FAQ específica del servicio → review si hay casos reales → CTA banner de cierre → footer. Cada pieza viene de una collection o de site.ts, ninguna se escribe a mano. El layout (ServiceLayout.astro) ensambla; los componentes pintan; el JSON-LD lo emite el layout una sola vez con Service+Offer+Breadcrumb.

Página tipoMódulos que usaSchema que emite
Homebreadcrumbs (oculto), hero, category-card grid, section-menu, FAQ, CTA, footerWebSite + Organization (footer)
Catálogo (/productos)breadcrumbs, hero, section-heading, product-card grid, footerCollectionPage + ItemList
Ficha producto (/productos/<slug>)breadcrumbs, hero, product card relacionadas, category-detail, FAQ, footerProduct + Offer + Breadcrumb
Catálogo serviciosbreadcrumbs, hero, section-heading, service-card grid, footerCollectionPage + ItemList
Ficha serviciobreadcrumbs, hero, section-menu interno, section-heading, category-detail, FAQ, review (si hay), CTA banner, footerService + Offer + Breadcrumb
Blog index (/blog)breadcrumbs, hero, section-heading, category-card grid (artículos), section-menu, footerCollectionPage + Blog
Artículo (/blog/<slug>)breadcrumbs, post header, prose, related sidebar, CTA banner, footerArticle + Breadcrumb
Contactobreadcrumbs, hero, contact-form, FAQ, footerContactPage

Patrones avanzados del sistema

Componentes agnósticos del módulo. GaleriaDisenos, DisenoCard, MarcoMovil y Receta son componentes del kit que no saben nada de breadcrumbs ni de productos. Reciben slots y props neutrales, y se reusan en los doce módulos para mostrar variantes y patrones móviles. El día que se documenta un módulo nuevo, no se inventan componentes: se usan los del kit.

SSoT (single source of truth) en site.ts. Los datos de marca, contacto, redes sociales, taxonomía de categorías y mensajes pre-cargados de WhatsApp viven en un solo archivo. El footer lee SOCIAL, el header lee MENU, los CTAs leen WA_MESSAGES. Cambiar el número de WhatsApp es una edición de una línea que se propaga a las 120 páginas en el siguiente build. Esto es lo que permite mantener un sitio sin volver a tocar componentes.

Helpers que derivan en vez de duplicar. siblingsModules('breadcrumbs') devuelve el índice de la serie + 2 vecinos en estado listo + la home, derivado de MODULOS. waUrl(WA_MESSAGES.cotizar) arma el href de WhatsApp con encodeURIComponent y el número de marca. buildSchema('product', data) arma el JSON-LD desde el contrato de la página. Los componentes no concatenan strings; llaman al helper.

Audit gates en cada commit. El repo corre audit:meta (longitudes title/description) y astro check (TS strict) antes de cada build. Los gates fallan barato (segundos), no en producción. Los doce módulos pasan estos gates como precondición para entrar a main.

Checklist para llegar a referencia industrial

  • Doce módulos publicados como L3 (/modulos/<slug>) con el mismo molde de 10 secciones.
  • Veinticuatro artículos de blog que cubren cada módulo en dos ejes (técnico + estratégico).
  • Un artículo tesis (este) que enlaza los 24 y sirve de mapa de entrada.
  • Content Collections con Zod .strict() para productos, servicios, artículos, zonas, casos.
  • Regla B3 aplicada: un único emisor de JSON-LD por entidad por página.
  • Regla B4 aplicada: cero reseñas auto-emitidas, cero schema fabricado.
  • Sistema mobile-first con mobile.css + breakpoints fijos 1024/768/640/480/380.
  • audit:meta y astro check como gates de build.
  • siblingsModules() y waUrl() como helpers canónicos.
  • Sitemap automático con @astrojs/sitemap.
  • Deploy en Cloudflare Pages con Node 22 y GitHub Actions.

Preguntas frecuentes

¿Por qué doce módulos y no diez o quince?

Porque doce cubre el sitio de negocio canónico —marca, navegación, catálogo, confianza, conversión— sin sobre-modelar. Diez deja afuera review y CTA banner, que son los que más cambian la conversión real. Quince obliga a inventar módulos que se usan en uno de cada cinco sitios (media-gallery, pricing-table, comparison-table) y diluyen la disciplina. Los doce son los que pasan el test “este módulo se usa en más del 80% de los sitios profesionales”.

¿Qué pasa si mi sitio no necesita reviews o contact form?

No los uses. Cada módulo es independiente. El sitio mínimo viable son cuatro: header, hero, footer y al menos un módulo de contenido (category-card o product-card). Los otros ocho se agregan según el cliente. La biblioteca cubre los doce para no dejar al lector sin documentación cuando lo necesite, no para forzar el uso de todos.

¿Cuánto pesa el sitio final en producción?

Una home típica con los doce módulos pesa entre 80 y 150 KB de HTML+CSS+SVG, sin JavaScript de framework. Las imágenes mandan (suelen ser el 80% del peso de la página), y para eso vale la receta AVIF con q50 y 1280px de ancho. Cloudflare Pages sirve el HTML estático en menos de 50 ms desde el edge mexicano. Los Web Vitals están sobrados sin tunear: LCP en 1.2 s, CLS en 0 si respetas width/height intrínsecos.

¿Puedo usar este sistema con otro framework (Next, SvelteKit, Nuxt)?

El sistema arquitectónico sí: data-driven desde Markdown, un único emisor de schema, mobile-first con tokens, helpers que derivan. Los componentes no, porque dependen de Astro 6 (slot semantics, class:list, set:html, integraciones específicas). Si vas a portar, conserva la disciplina y reescribe los componentes en la sintaxis del framework destino. La parte que más se traduce es el contrato de schema y la regla B3/B4.

¿Cómo agrego el módulo trece, catorce, quince?

El repo tiene un slot abierto para whatsapp-flotante (módulo 13) y la lista en MODULOS deja espacio para más. La receta es la del documento docs/MODULOS.md: crear el componente en src/components/, escribir la página L3 en src/pages/modulos/<slug>.astro con las diez secciones canónicas, agregarlo al array MODULOS con estado: 'listo', y publicar dos artículos en src/content/articulos/ siguiendo el patrón técnico + estratégico. Cuando el módulo trece esté listo, vuelve a esta tesis y actualízala —es el ancla del sistema, debe reflejar la realidad de la biblioteca.

Cierre

Los doce módulos no son una opinión: son el resultado de auditar diez sitios profesionales y quedarse con los bloques que sí se repiten. Los veinticuatro artículos no son contenido para llenar el blog: son la documentación que permite que otro developer arme el mismo sistema en otro proyecto sin reinventar las decisiones. Si llegaste hasta aquí, el siguiente paso es leer el módulo que te interesa, leer los dos artículos que lo cubren, abrir el código del repo y empezar a construir. El sistema está completo y probado en producción; lo que falta es que lo uses.

Sigue leyendo

¿Listo para dar el siguiente paso?

Cuéntanos qué necesitas y te respondemos hoy mismo.

¿Necesitas ayuda?