Arquitectura web en 2026: home como app, el resto estático
Casi todos los sitios tratan cada página como una SPA. Nosotros hacemos lo contrario: la home como aplicación, el resto como documentos estáticos. Dos targets.
Un sitio de marketing para SaaS son dos productos disfrazados de uno. La home soporta el peso de la conversión. El resto soporta el peso de la confianza. Casi todos los equipos los construyen con la misma arquitectura y luego se preguntan por qué la home parece lenta y el blog sobredimensionado.
Nuestra división: la home se construye como una single-page app, con estado, interacción, presupuesto de animación. Todo lo demás (sobre nosotros, servicios, case studies, blog, contacto, manifiesto, páginas del stack) se sirve como documento estático. Targets de build distintos, rutas de código distintas, presupuestos de rendimiento distintos.
No es una elección lista de framework. Es una lectura de dónde están realmente la atención y la intención en un sitio SaaS.
Los dos defaults que casi siempre se eligen
Primer default: "todo es una SPA". Coges Next.js, hidratas cada página, el blog usa el mismo router del lado cliente que el dashboard. La home va bien. El blog tiene un INP de 400ms y un LCP que depende de lo rápido que tu CDN sirva un bundle JS. Los crawlers esperan a la hidratación. El equipo añade complejidad incremental para arreglar lo que fue una decisión estructural.
Segundo default: "todo es estático". Coges Astro o Hugo, prerenderizas home, blog, case studies, contacto. El blog vuela. La home parece muerta. Las animaciones que el founder pidió ahora son una pelea con el framework, no una función suya. El equipo añade complejidad incremental para arreglar lo que fue una decisión estructural.
Ambos defaults tratan home y páginas-documento como el mismo producto. No lo son.
La home es una app. El resto es un documento.
La home tiene un trabajo concreto: coger a quien llega desde una búsqueda en Google, un enlace de X, un podcast, una cita de un motor IA, y llevarlo hacia un contacto. La decisión ocurre en 8-15 segundos. El diseño tiene que trabajar en esa ventana: hero animado, reveal al scroll, una demo interactiva, una CTA con estado que sabe si ya has pasado por aquí.
Nada de eso es teatro. Es la superficie de conversión ganándose su presupuesto.
El case study en /es/proyectos/kibank hace otro trabajo. Existe para quien ya vio la home, entró en un case study y ahora quiere tres datos: cuál era el problema, qué entregamos, qué cambió. Esa persona quiere que el texto cargue al instante, que las imágenes no salten, y que la página haga scroll sin que animaciones a 60fps le corten la lectura. El case study es un documento.
El artículo del blog que estás leyendo ahora también es un documento. Existe para que lo cite ChatGPT, lo indexe Google y lo lea un product owner con un café. Cada gramo de JavaScript en esta página es un impuesto sobre ese trabajo.
Cómo se construye la división en Next.js 16
La implementación se apoya en tres primitivas que el App Router te da gratis, si las montas con criterio:
- Estático por defecto, dinámico por opt-in. Las páginas-documento no exportan ninguna señal de rendering dinámico. Nada de
cookies(), nada deheaders(), ningúnsearchParamsen la ruta de render. Se prerenderizan en build y se sirven desde una CDN. El TTFB baja por debajo de 100ms en el edge de Vercel. - Suspense como frontera. La home usa Partial Prerendering, estable desde Next.js 16: una shell estática (nav, hero copy, footer) se renderiza al instante, luego las partes dinámicas (contador en vivo de testimonios, variante de CTA en A/B test, estado signed-in) entran por streaming detrás de
Suspense. La shell está en la CDN. Las partes dinámicas, en el runtime. - Ningún client component en las páginas-documento. Case studies y posts del blog no usan ni un
"use client". El único JavaScript que llega al navegador es el toggle de tema global y el selector de idioma. Los dos están aislados en el header. El cuerpo del documento no carga coste de hidratación.
La home puede importar GSAP, Lenis para el scroll suave, y una animación hero que corra en cada paint. Las páginas-documento no. La restricción se aplica en la capa de routing: cualquier cosa bajo app/[lang]/(public)/(docs)/ pasa por un layout que no carga el runtime de animación.
Por qué esto salva números concretos
Las páginas-documento salen con un LCP en torno a 0.8s en una 4G rápida, un INP por debajo de 80ms (porque casi no hay con qué interactuar) y un TTFB al suelo de la CDN. Los umbrales Core Web Vitals 2026 (LCP por debajo de 2.5s, INP por debajo de 200ms, TTFB por debajo de 800ms) no son una meta a alcanzar: son un suelo bajo el que estamos cómodos. La parte amplia sobre Vitals la cubrimos en Core Web Vitals en Next.js en 2026.
La home carga más. Target LCP 1.5s, target INP 150ms, y el presupuesto de animación más pesado se permite porque la shell se renderiza antes de que cargue nada de eso. La página parece viva pero el primer paint útil no espera a la timeline de GSAP.
Para los sitios de marketing SaaS, en 2026 el benchmark competitivo de LCP se ha apretado de 2.5s a por debajo de 2.0s. Dividir la arquitectura es uno de los pocos movimientos que te llevan ahí sin tocar el contenido.
Dónde las páginas-documento devuelven la pelota a la app
La trampa de esta división es tratar las páginas-documento como segunda fila. No lo son. Son la superficie de cita para los motores IA, la superficie de indexación para Google, la superficie de lectura para quien no convierte en la primera visita. Generan tráfico de cola larga que la home no puede captar, y alimentan a la home con enlaces internos.
La autoridad fluye de las páginas-documento a la home si desde los documentos enlazas hacia la superficie de conversión. Sin ese patrón, un documento que se gana 400 backlinks al año no pasa equity interna a la página principal. Usamos un bloque footer (renderizado por la plantilla, no por el HTML del artículo) que desde cada documento devuelve a una superficie "cuéntanos qué estás construyendo".
Los trade-offs que aceptamos
Esta división no es gratis.
- El design system tiene que ser solo CSS. Si la librería de componentes envía primitivas pesadas en JavaScript (un dropdown que se abre con state de React, un date picker atado a un runtime), no se pueden usar en las páginas-documento sin romper la regla del no-hydration. Por la misma razón quitamos Tailwind de producción: los tokens son variables CSS, los componentes son clases CSS, el presupuesto JS es cero por defecto.
- Dos rutas de render son dos superficies de bug. Una animación que funciona en la home no necesariamente funciona en una página-documento. El equipo tiene que recordar de qué lado de la línea está.
- Las fronteras de Suspense se rompen. Si un server component hace fetch sin un wrapper Suspense, la shell estática no se renderiza hasta que llegan los datos. Partial Prerendering solo funciona si cada fetch dinámico está acotado.
- Búsqueda y filtros en páginas-documento son complicados. Un índice de blog con búsqueda en vivo necesita un client component. Aceptamos esa excepción: la búsqueda es un client component, pero vive en su isla y no hidrata el cuerpo del artículo.
Cuándo no hacerlo
Si tu sitio es una landing única sin blog, sin case studies, sin documentación, no lo dividas. El coste de mantener dos render paths es mayor que la ganancia.
Si tu sitio es la app SaaS en sí (todo detrás del login), no lo dividas. El sitio entero es una app. El rendering estático para un dashboard logueado es un problema distinto con una solución distinta, y ahí pesa más la elección entre edge y Node runtime.
La división se gana su peso cuando tienes una o dos páginas de conversión de alto valor (home, landings clave, pricing) y una cola larga de páginas de contenido que existen para informar, posicionar y ser citadas. Esa es la forma modal de un sitio de marketing SaaS en 2026.
La versión corta
Un producto, dos targets de render, una convención de routing que hace cumplir la línea. La home se gana ser una app porque lo merece. El resto del sitio se queda como documento porque es lo que el visitante quiere de verdad, y es lo que Google y los motores IA premian.
Preguntas frecuentes
- ¿En qué se diferencia esta división de un setup estándar de Next.js donde todas las páginas pasan por el App Router?
- Un Next.js estándar hace pasar todo por la misma pipeline de rendering. La división aquí se aplica a nivel de layout: un route group separado para las páginas-documento quita los client components, el runtime de animación y cualquier acceso a APIs dinámicas. El framework es el mismo, pero las restricciones dentro de cada grupo son distintas. La línea se ve en el árbol de carpetas, no en una build config.
- ¿Cómo se mantiene coherente el design system cuando la mitad del sitio no tiene JavaScript?
- El design system tiene que ser solo CSS por diseño. Los tokens son variables CSS, los componentes son clases CSS, ninguna primitiva pide JavaScript. El mismo Button se renderiza idéntico en la home (donde la página alrededor está hidratada) y en un post del blog (donde no lo está). Si una primitiva necesita JavaScript para funcionar (un dropdown, un date picker, un combobox), vive en su propia isla cliente y se usa solo en el lado app de la línea.
- ¿Esta división funciona en Astro o Remix en lugar de Next.js?
- Sí, con mecánicas distintas. Astro está construido alrededor de un modelo de islas y te regala el lado documento casi gratis: la home se convierte en una sola isla hidratada. Remix puede hacer lo mismo con su patrón de loaders y rutas cliente selectivas. El principio (un producto, dos targets de render, una convención de routing que hace cumplir la línea) es agnóstico al framework. Solo cambia la sintaxis de la frontera.
Studio
Empieza un proyecto.
Un partner único para el producto digital que necesitas construir. Producción más rápida, tecnología moderna, costes reducidos. Un equipo, una factura.