Headless WordPress + Next.js: cómo migrar y por qué hacerlo
Headless WordPress separa el CMS (panel de administración y contenido) del frontend. En este enfoque, WordPress actúa como fuente de datos y Next.js renderiza el sitio usando SSR/SSG/ISR. El resultado: más rendimiento, mejor DX (Developer Experience) y una arquitectura preparada para escalar.
¿Por qué migrar a Headless con Next.js?
- Rendimiento superior: páginas estáticas (SSG) e Incremental Static Regeneration (ISR) para latencias muy bajas.
- SEO sólido: HTML prerenderizado, control total de metadatos y rutas limpias.
- Experiencias ricas: React + ecosistema moderno (TypeScript, SWR/React Query, Tailwind, etc.).
- Escalabilidad y seguridad: el panel WP queda aislado; el público consume solo el frontend desplegado en CDN.
- Multicanal: sirve el mismo contenido a web, apps móviles o dispositivos IoT desde WordPress.
Antes de empezar
- Actualiza WordPress, PHP (8.1+), base de datos y revisa compatibilidad de plugins.
- Define modelo de contenido (Entradas, Páginas, CPT, taxonomías, campos ACF, etc.).
- Elige API: WPGraphQL (recomendado) o REST API nativa.
Stack recomendado
- WordPress (Headless) con plugins: WPGraphQL, WPGraphQL for ACF (si usas ACF), JWT o OAuth (si requieres auth).
- Next.js 14/15 con App Router, TypeScript,
next/image
,next-seo
o metadatos del App Router. - Vercel (o similar) para despliegue con ISR y CDN global.
Pasos para la migración
1) Preparar WordPress como API
- Instala y configura WPGraphQL (o expón rutas de REST API).
- Modela el contenido: CPT, taxonomías y campos (ACF). Verifica que el esquema GraphQL exponga todo lo necesario.
- Crea webhooks (por ejemplo con WP Webhooks) que notifiquen a Next.js para revalidar páginas al publicar/actualizar.
- Activa CORS para permitir peticiones desde tu dominio del frontend.
2) Crear el proyecto Next.js
npx create-next-app@latest headless-wp --ts
cd headless-wp
npm i @apollo/client graphql # (si usas GraphQL)
# o bien npm i swr axios # (si prefieres REST + SWR)
Ejemplo con GraphQL (App Router)
lib/apollo-client.ts
import { ApolloClient, InMemoryCache } from "@apollo/client";
export const client = new ApolloClient({
uri: process.env.NEXT_PUBLIC_WP_GRAPHQL_ENDPOINT,
cache: new InMemoryCache(),
});
app/page.tsx (home estática con revalidación)
import { gql } from "@apollo/client";
import { client } from "@/lib/apollo-client";
export const revalidate = 60; // ISR: revalida cada 60s
export default async function Home() {
const { data } = await client.query({
query: gql`{
posts(first: 6) { nodes { id title uri excerpt } }
}`,
fetchPolicy: "no-cache"
});
return (
<main>
<h1>Blog</h1>
<ul>
{data.posts.nodes.map((p: any) => (
<li key={p.id}><a href={p.uri}>{p.title}</a></li>
))}
</ul>
</main>
);
}
Rutas dinámicas de posts
app/[…slug]/page.tsx
import { gql } from "@apollo/client";
import { client } from "@/lib/apollo-client";
export const revalidate = 300;
export async function generateStaticParams() {
const { data } = await client.query({
query: gql`{ posts(first: 100) { nodes { slug } } }`,
fetchPolicy: "no-cache"
});
return data.posts.nodes.map((n: any) => ({ slug: [n.slug] }));
}
export default async function Post({ params }: { params: { slug: string[] } }) {
const slug = params.slug.at(-1);
const { data } = await client.query({
query: gql`query ($slug: ID!) {
post(id: $slug, idType: SLUG) { title content date featuredImage { node { sourceUrl width height } } }
}`,
variables: { slug },
fetchPolicy: "no-cache"
});
const post = data.post;
return (
<article>
<h1>{post.title}</h1>
{post.featuredImage?.node && (
<img src={post.featuredImage.node.sourceUrl} width={post.featuredImage.node.width} height={post.featuredImage.node.height} alt={post.title} />
)}
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
3) Imágenes y CDN
- Usa
next/image
con el dominio del WP configurado ennext.config.js
para optimización automática. - Considera mover la librería multimedia a un bucket S3/Cloud Storage con plugin (Offload Media) para menos carga al WP.
4) SEO, metadatos y sitemap
- En App Router, define
generateMetadata
o instalanext-seo
. - Genera
/sitemap.xml
y/robots.txt
connext-sitemap
.
5) Vista previa de borradores (Preview Mode)
- Crea una ruta API en Next.js (
/api/preview
) que valide un token y habilite el modo preview. - En WordPress, configura la URL de vista previa para apuntar a esa ruta con el
postId
.
6) Revalidación por webhook
En /app/api/revalidate/route.ts
:
import { NextRequest, NextResponse } from "next/server";
export async function POST(req: NextRequest) {
const secret = req.nextUrl.searchParams.get("secret");
if (secret !== process.env.REVALIDATE_SECRET) return NextResponse.json({ ok: false }, { status: 401 });
const path = (await req.json()).path || "/";
try {
// @ts-ignore: disponible en runtime de Vercel
await res.revalidate(path);
return NextResponse.json({ revalidated: true, path });
} catch (e) {
return NextResponse.json({ revalidated: false, message: String(e) }, { status: 500 });
}
}
Desde WordPress, envía el webhook al publicar y pasa la ruta afectada.
Consideraciones y buenas prácticas
- Autenticación: para áreas privadas, usa JWT/OAuth y middleware de Next.
- Cache: SWR/React Query en cliente y caché de fetch en servidor; evita sobrecargar al WP.
- Accesibilidad y i18n con
next-intl
onext-i18next
. - Monitorización: registra métricas Web Vitals y errores (Sentry/LogRocket).
Desventajas (lo que debes saber)
- Mayor complejidad inicial que un tema clásico de WordPress.
- Algunas funciones de plugins visuales no aplican directamente al frontend (requieren integración vía API).
- Coste operativo: CMS + hosting del frontend + posibles servicios de medios/edge.
Checklist de migración
- ✓ Inventario de contenido y URL actuales (para redirecciones 301).
- ✓ API lista (WPGraphQL/REST) y esquema validado.
- ✓ Next.js con SSG/ISR y rutas equivalentes.
- ✓ SEO: metadatos, sitemap,
robots.txt
, canonicals y redirects. - ✓ Webhooks de revalidación y vista previa de borradores.
- ✓ Pruebas de rendimiento, accesibilidad y core web vitals.
Conclusión
Migrar a Headless WordPress + Next.js ofrece un salto notable en rendimiento, seguridad y flexibilidad. Si tu proyecto necesita velocidad, SEO robusto y una UX moderna, el enfoque headless es una apuesta ganadora.
👉 ¿Quieres que planifiquemos y ejecutemos tu migración headless de principio a fin?
Contáctanos aquí.