← Volver al blog
06 de mayo de 2026·Lectura: 3 minIngenieria

Como construi este blog (y por que debi elegir Nuxt desde el dia 1)

Cronica tecnica de arquitectura de blog: errores de arranque, intento con VitePress, dolor de mantenimiento y refactor build-time con foco en SEO y performance.

Spoiler tecnico: El blog funciona, escala y ya no me quita el sueño. Pero el camino fue un “aprendizaje acelerado con efectos secundarios”.

Portada del articulo: decisiones de arquitectura entre Vue, VitePress y Nuxt.

Prologo: cuando el entusiasmo le gana al diseño

Esta historia empieza como empiezan muchas historias de software:

  1. “Esto sale rapido.”
  2. “Luego lo ordeno.”
  3. “No necesito meter otra capa.”
  4. “Oh no.”

Yo queria un portafolio rapido en Vue 3 + Vite, con buen performance y una seccion de blog. Hasta ahi, todo bien.

El problema fue asumir que “blog” era solo “pintar markdown”. En realidad era:

  • contenido,
  • SEO,
  • rutas,
  • generacion de artefactos,
  • performance,
  • validaciones,
  • y disciplina.

En ese punto, Nuxt ya me estaba viendo desde lejos con cara de: “te lo dije”.

Acto 1: la version YOLO del blog

Mi primer impulso fue resolver todo en runtime cliente:

  • leer markdown,
  • parsearlo,
  • resaltarlo con Shiki,
  • y rezar para que el bundle no explotara.

Si quieres detectar rapido que algo no va bien, revisa el tamano del chunk. Cuando ves que la pieza de markdown/highlighting crece como si entrenara para una competencia, sabes que hay deuda tecnica.

Leccion: renderizar markdown + highlighting en cliente para un blog tecnico no es gratis.

Acto 2: “metamos VitePress y ya”

Aqui fue donde me puse creativo de la manera equivocada. Pense: “Si VitePress resuelve docs/blog, lo encajo en el proyecto y listo.”

No era mala intencion. Si fue mala friccion.

Problemas reales de ese intento:

  1. Dos modelos mentales conviviendo sin hablarse del todo.
  2. Acoplamientos raros entre rutas/app y contenido.
  3. Flujo editorial menos directo para este caso.
  4. Mantenimiento mas caro para algo que debia simplificar.

Traduccion: quise ahorrar tiempo y termine pagando interes compuesto.

Timeline horizontal de cuatro hitos: arranque rapido, intento con VitePress, dolor de mantenimiento y refactor build-time.

Acto 3: la arquitectura que si se quedo

En lugar de perseguir magia, dividi el problema en capas simples:

  1. content/blog/<locale>/*.md como fuente de verdad.
  2. Scripts de build para generar artefactos consumibles.
  3. Runtime cliente delgado (sin parsear markdown pesado).
  4. Rutas y SEO consistentes en SSG.

Estructura real (simplificada)

content/
  blog/
    es/
      *.md
  media/
    blog/
      <slug>/

scripts/
  build-blog-content-artifacts.mjs
  build-blog-artifacts.mjs

src/features/blog/generated/
  blog-index.es.json
  blog-posts/es/<slug>.html
  blog-routes.json

Flujo de build del blog

Markdown en content/blog/es
  -> Build de artefactos
    -> indice JSON por locale
    -> HTML pre-render por slug
    -> rutas SSG publicables
      -> listado ligero
      -> detalle de post sin parseo runtime
      -> prerender estable con vite-ssg
Diagrama de arquitectura final: contenido markdown, scripts de build, artefactos generados y runtime liviano.

Que gano con esto

  • Menos JS en cliente para blog.
  • Menos trabajo duplicado entre listado y detalle.
  • Menos sorpresas en SEO y rutas.
  • Mejor mantenibilidad del contenido.

Practicas que se aplican hoy (y por que importan)

No es solo “que compile”. Es que se sostenga.

1) Contratos de contenido

  • Frontmatter validado por esquema.
  • lang consistente con carpeta.
  • slug estable.
  • canonical correcto.

Esto evita que un post bonito rompa produccion por un typo silencioso.

2) Seguridad de supply chain

En .npmrc:

  • ignore-scripts=true
  • save-exact=true
  • min-release-age=2

No suena glamuroso. Si suena a dormir tranquilo.

3) Performance con presupuesto

No se optimiza “a ojo”. Se optimiza con limites:

  • budget de JS inicial,
  • budget de chunk de detalle de blog,
  • validaciones en CI.

Cuando algo se sale, falla. Como debe ser.

Comparativa visual de carga runtime pesada vs build-time pre-renderizado.

4) Separacion de responsabilidades

Cliente:

  • renderizar UX.

Build:

  • cocinar contenido pesado.

Resultado: el navegador deja de hacer trabajo de cocina industrial.

Infografia de pilares: contratos de contenido, supply chain, budgets de performance y SSG.

Fragmentos tecnicos del proyecto

Scripts clave

{
  "scripts": {
    "build:blog-content-artifacts": "node ./scripts/build-blog-content-artifacts.mjs",
    "build:blog-artifacts": "node ./scripts/build-blog-artifacts.mjs",
    "build": "npm run build:blog-artifacts && vue-tsc --noEmit && vite-ssg build"
  }
}

Carga de artefactos en runtime (idea)

const blogIndexArtifactModules = import.meta.glob(
  "/src/features/blog/generated/blog-index.*.json",
  { eager: true, import: "default" }
);

Resultado practico

El detalle de post ya consume HTML generado. No parsea markdown pesado en cliente en cada navegacion.

Y entonces, por que Nuxt desde el dia 1?

Porque varias piezas que yo cosi manualmente, Nuxt te las entrega mas integradas desde el inicio para contenido, rutas y ciclo editorial.

No es que la solucion final actual sea mala. Es que Nuxt me habria dejado invertir mas tiempo en producto y menos tiempo en pegamento.

Referencia clave que hoy pesaria en esa decision:

Cierre

Este blog no nacio perfecto. Nacio util, luego terco, luego mantenible.

Y si este post te evita meter un framework “porque si” o reescribir media arquitectura en viernes por la noche, mision cumplida.

Siguiente lectura