Sitio servicios-céntrico: retirar el andamiaje de catálogo
La plantilla nace catálogo-céntrica (productos tejidos en footer, menú y CTAs). Guía para convertirla a un negocio de servicios sin romper el build.
El menú decía «Productos». El negocio era una agencia de desarrollo web: vende criterio, horas y un portafolio de sitios entregados, no piezas con SKU. Cuando abrimos su reconstrucción sobre esta plantilla, el síntoma estaba ahí, arriba a la derecha, en la barra de navegación: una sección de catálogo para alguien que no tiene catálogo. Y no era solo el menú. La columna del footer ofrecía «categorías de producto», los enlaces relacionados de cada página cruzaban a fichas que no existían, los presets de llamada a la acción decían «Ver catálogo», y el astro.config tenía redirecciones de /productos apuntando al vacío. La plantilla, diseñada para un comercio, estaba peleándose con un negocio de servicios en quince archivos a la vez.
Ese desajuste no se arregla borrando una carpeta. La colección productos no vive aislada: está tejida en el marco del sitio, y retirarla a medias deja un Frankenstein —menús que llevan a un 404, schema Product sin productos, footers que prometen un catálogo inexistente—. Esta guía es el procedimiento ordenado para convertir la plantilla de catálogo-céntrica a servicios-céntrica, en el orden exacto que mantiene el build verde en cada paso. Es el camino que recorrimos al llevar un sitio insignia de agencia al estándar, y la mayoría de lo que aprendimos fue sobre el orden de las operaciones, no sobre el código en sí.
Por qué la plantilla nace catálogo-céntrica
La decisión es deliberada y vale la pena entenderla antes de deshacerla. Un catálogo de productos es el caso más exigente de toda la maquinaria: ejercita el índice de sección (L2), la ficha de detalle (L3), las variantes (L4), el schema Product con su Offer, las tarjetas con doble llamada a la acción y los filtros por categoría, todo a la vez. Si el sistema sostiene un catálogo, sostiene cualquier cosa más simple. Por eso la plantilla trae productos como colección de demostración y la cablea en los módulos compartidos: para que el ejemplo se vea íntegro desde el primer npm run dev, sin huecos.
El costo de esa integridad es que «más simple» se construye quitando, y quitar de un sistema cableado exige más cuidado que añadir a uno vacío. Cuando agregas una sección nueva, partes de cero y nada depende de ella todavía. Cuando retiras una que llevaba meses tejida, cada hilo que cortas puede estar sosteniendo otra cosa. De ahí que esta conversión sea, en esencia, una resta cuidadosa.
Los dos arquetipos, y cómo saber en cuál estás
Un negocio catálogo-céntrico organiza su oferta en cosas contables —piezas, modelos, referencias— y su página de conversión es la ficha de producto. Un negocio servicios-céntrico organiza su oferta en capacidades —consultoría, desarrollo, mantenimiento— y convierte en la ficha de servicio y en el portafolio que prueba el trabajo hecho. Ambos corren sobre la misma maquinaria: colecciones tipadas con Zod, niveles L1–L4, SEO centralizado en lib/seo.ts, módulos reutilizables. Lo único que cambia es la colección protagonista: productos cede el lugar a servicios, y el «catálogo» como prueba social se reemplaza por un portafolio de casos reales.
La prueba para saber en cuál estás es de una línea: si tu menú dice «Productos» pero lo que vendes es tu tiempo y tu juicio, el andamiaje no coincide con el negocio. Ese desajuste, además de raro para el visitante, ensucia el SEO —rankeas por términos de catálogo que no te interesan— y el grafo de datos —emites Product sin productos que respalden el schema—.
Implementación paso a paso
El secreto de toda la conversión es uno: el data layer antes que el disco. Si borras archivos primero, el build truena por referencias colgantes y pierdes la brújula. Si desconectas las referencias primero, el build te va diciendo, en verde o rojo, si vas bien.
Paso 1 — Decidir qué colección manda
Antes de tocar una línea, escribe la decisión: en un sitio de servicios, servicios manda; productos se retira; la prueba social del catálogo se reemplaza por casos o por un portafolio propio; zonas se conserva si hay SEO local. No es burocracia: cada una de esas decisiones se traduce, en los pasos siguientes, en archivos concretos. Decidir primero evita el peor escenario, que es retirar a media máquina y no recordar qué reemplazaba a qué.
Paso 2 — Desconectar productos del data layer
En content.config.ts, saca productos del export de collections y borra toda reference('productos') de las demás colecciones. Aquí está el primer cabo que casi siempre se olvida: servicios, articulos y casos traen campos relatedProducts que apuntan al schema que vas a quitar. Una reference() colgante hace fallar el build con un error de colección desconocida —y esa es la red de seguridad de Zod trabajando a tu favor, avisándote del hilo suelto antes de que llegue a producción—.
// content.config.ts — antes
export const collections = { productos, servicios, articulos, zonas, casos };
// después (servicios-céntrico)
export const collections = { servicios, articulos, zonas, casos };
// y en CADA colección que lo tuviera, fuera el campo de referencia:
// relatedProducts: z.array(reference('productos')).optional(), ← eliminar
// si no, el build truena con "Collection 'productos' does not exist".
Paso 3 — Repuntar los módulos compartidos
Aquí está el trabajo real, el que toma una tarde. Cuatro puntos de enganche apuntan a productos y hay que reorientarlos, uno por uno, a servicios (o a portafolio):
SectionMenuyHeader: el ítem «Productos» del menú principal pasa a «Servicios», con suhrefreal.Footer: la columna que listaba categorías de producto ahora lista servicios o secciones reales. El footer es SEO global; un enlace muerto ahí pesa en todas las páginas del sitio, no en una.RelatedLinks: el bloque de enlaces relacionados que cruzaba a productos ahora cruza a servicios y casos.cta-presets.ts: los presets que decían «Ver catálogo» pasan a «Ver servicios» o «Cotizar», con copy yhrefhonestos.
Repunta un módulo, corre astro check, repunta el siguiente. Esa cadencia —cambio, verifica, cambio— convierte un refactor opaco en una serie de pasos reversibles: si algo se rompe, sabes que fue el último, no uno de quince.
Paso 4 — Eliminar rutas y redirecciones
Borra src/pages/productos/ completo —índice, ficha dinámica, variantes— y, crucial, quita las redirecciones /productos del astro.config. Una redirección huérfana hacia una ruta que ya no existe genera un destino muerto que los validadores marcan y que Googlebot persigue hasta toparse con nada. Es el cabo más invisible de todos porque no está en una página, está en la configuración, y por eso es el que más sobrevive a las limpiezas apresuradas.
Paso 5 — Reconstruir el índice de servicios data-driven
Con el andamiaje fuera, reescribe src/pages/servicios/index.astro como un índice L2 limpio que lee de la colección con getCollection, pinta un ServiceCard por entrada y cierra con un CTABanner. Nada de HTML horneado ni de componentes de demostración acoplados —en la reconstrucción real, la página de servicios del template venía amarrada a componentes-guía y fue más rápido reescribirla limpia que desenredarla—.
---
import { getCollection } from 'astro:content';
const servicios = (await getCollection('servicios'))
.filter((s) => !s.data.draft)
.sort((a, b) => a.data.order - b.data.order);
---
Patrones avanzados
El footer fantasma. El footer es el módulo que más se olvida porque está «abajo» y rara vez se mira al maquetar. Pero es SEO global: vive en todas las páginas y sus enlaces reparten autoridad. Un enlace a /productos olvidado en el footer no es un error de una página, es un error de todo el sitio multiplicado por el número de páginas. Revísalo explícitamente, no de pasada.
La entrega bajo FUSE: cp, no tar. Si reconstruyes en un entorno y entregas a otro montado por FUSE (un sandbox, un volumen remoto), cuidado: tar -x no sobreescribe archivos que ya existen en el destino y deja la versión vieja sin avisar (sale con código 2 y sigue). El resultado es un sitio mitad nuevo, mitad viejo, imposible de depurar. Usa cp —que trunca y reescribe— o las herramientas de edición directa. Este detalle nos costó una confusión entera antes de identificarlo.
El grep como juez de la limpieza. No confíes en tu memoria de los quince archivos. La conversión está completa cuando el sitio compilado no menciona la sección retirada, y eso se mide, no se recuerda.
npm run build
grep -rl "/productos" dist/ && echo "AÚN HAY RASTROS" || echo "OK: cero rutas /productos en dist"
Migrar la prueba social, no descartarla. Retirar el catálogo no significa quedarse sin prueba. La ficha de producto se cambia por la ficha de proyecto, con schema CreativeWork en lugar de Product. Es un tema con suficiente sustancia propia que lo tratamos aparte, en Portafolio honesto: proyectos vs casos.
Edge cases
El sitio que vende ambas cosas. Algunos negocios venden servicios y productos de verdad (una empresa de seguridad que instala y también vende equipo). Ahí no retiras productos: conservas las dos colecciones y decides cuál es la protagonista del menú y la home según de dónde venga el dinero y el tráfico. La conversión de esta guía es para quien tiene catálogo de demostración sin negocio de catálogo detrás.
Las imágenes huérfanas. Al borrar src/pages/productos/ quedan en public/images/productos/ un montón de imágenes que ya nada referencia. No rompen el build, pero inflan el deploy. Una pasada de limpieza posterior —cotejando qué imágenes siguen referenciadas— recupera peso.
El sitemap que recuerda. Si tu sitemap se genera de las rutas, se actualiza solo. Si lo mantienes a mano (anti-patrón), recuerda quitar las URLs de /productos: un sitemap que lista páginas inexistentes le enseña a Google a desconfiar del archivo entero.
Tabla: qué tocar al convertir
| Punto de enganche | Estado catálogo | Acción servicios-céntrico |
|---|---|---|
content.config.ts | productos en export + reference() | Quitar del export y borrar referencias |
SectionMenu / Header | Ítem «Productos» | A «Servicios» / «Portafolio» |
Footer | Columna de categorías de producto | A servicios / secciones reales |
RelatedLinks | Cruce a productos | Cruce a servicios / casos |
cta-presets.ts | «Ver catálogo» | «Ver servicios» / «Cotizar» |
src/pages/productos/ | Índice + ficha + variantes | Eliminar |
astro.config | Redirects /productos | Eliminar |
src/pages/servicios/index | Demo acoplada a componentes-guía | Reescribir data-driven |
Checklist
- Decide por escrito la colección protagonista (
servicios) y el reemplazo de la prueba social (casos/portafolio). - Quita
productosdelexporty borra todareference('productos')antes de tocar el disco. - Repunta
SectionMenu,Header,Footer,RelatedLinksycta-presets.ts, verificando conastro checktras cada uno. - Elimina
src/pages/productos/y las redirecciones/productosdelastro.config. - Reescribe el índice de servicios data-driven (
getCollection+ServiceCard+CTABanner). - Cierra con
astro checken cero,grep -rl "/productos" dist/vacío y unbuildverde.
Preguntas frecuentes
¿Por qué no empezar de cero en vez de retirar el catálogo?
Porque la maquinaria —colecciones tipadas, niveles, lib/seo.ts, módulos, layouts— es la misma y vale oro conservarla. Lo único que cambia es la colección protagonista. Retirar y repuntar es más rápido y mucho más seguro que reconstruir el sistema entero, y heredas todas las decisiones de calidad que el template ya trae resueltas.
¿En qué orden hago los cambios para no romper el build?
Data layer primero (quitar del export y borrar las reference()), luego módulos compartidos uno por uno verificando entre cada uno, luego rutas y redirecciones, y al final el índice nuevo. Si inviertes el orden y borras los archivos antes que las referencias, el build truena y pierdes la señal de qué falta.
¿Tengo que borrar la carpeta src/content/productos/?
Sacarla del export y de las reference() ya la retira del sitio. Borrar la carpeta es opcional pero recomendable: deja el repositorio honesto y evita que el siguiente que lo abra crea que el catálogo sigue vivo. Lo mismo aplica a public/images/productos/.
¿Cómo confirmo que no quedó ningún cabo suelto?
El build es el juez. astro check en cero atrapa las referencias rotas de Zod, y un grep -rl "/productos" dist/ vacío confirma que no quedan rutas ni enlaces a la sección retirada. Si ambos pasan, la conversión es real, no aparente.
¿Conservo la colección zonas?
Sí, si el negocio tiene SEO local (atiende ciudades o alcaldías concretas). zonas es ortogonal al arquetipo catálogo/servicios: aporta cobertura geográfica en ambos y no estorba la conversión.
¿Y si el negocio realmente vende servicios y productos?
Entonces no es una conversión, es una decisión de jerarquía: conservas ambas colecciones y eliges cuál protagoniza el menú y la home según de dónde viene el ingreso y el tráfico. Esta guía es para el caso —muy común— de un catálogo de demostración sin negocio de catálogo detrás.
Sigue leyendo
- Los 4 niveles de un sitio: de la raíz a la hoja — la arquitectura L1–L4 que comparten catálogo y servicios.
- Índices de sección en Astro: getCollection e ItemList — cómo se construye el índice de servicios data-driven del paso 5.
- Portafolio honesto: proyectos vs casos — la prueba social que reemplaza al catálogo.
- Auditar y migrar un sitio existente al estándar — el método página por página dentro del que encaja esta conversión.
- Fuente externa: Astro Docs — Content Collections y Astro Docs — Redirects.