Contents
Introducción
Este tutorial explica con todo lujo de detalles cómo consumir una instalación de WordPress desde una aplicación Next.js usando la REST API nativa de WordPress. Cubriremos desde la configuración básica y ejemplos prácticos de fetch (en getStaticProps, getServerSideProps y en cliente con SWR), hasta autenticación (JWT), creación de endpoints personalizados, manejo de imágenes y buenas prácticas de rendimiento y seguridad. Los ejemplos incluyen fragmentos listos para copiar y adaptar.
Requisitos
- WordPress 4.7 (la REST API está incluida a partir de esa versión).
- Acceso al servidor para instalar plugins o editar functions.php si necesitas endpoints personalizados o autenticación JWT.
- Proyecto Next.js (12 recomendado, pero las ideas valen para Next 13 con app router adaptando la sintaxis).
- Conocimientos básicos de JavaScript/React y PHP para la parte de WordPress.
Arquitectura general y endpoints útiles
La REST API de WordPress expone recursos importantes en rutas como:
- /wp-json/wp/v2/posts — lista y detalle de entradas.
- /wp-json/wp/v2/pages — páginas.
- /wp-json/wp/v2/categories y /wp-json/wp/v2/tags.
- /wp-json/wp/v2/media — archivos multimedia.
- /wp-json/wp/v2/comments — comentarios.
Además hay complementos y plugins que exponen endpoints adicionales (por ejemplo ACF o JWT Auth). Si prefieres GraphQL, puedes usar el plugin WPGraphQL.
Conceptos clave antes de empezar
- Headless WordPress: WordPress actúa como CMS y ofrece contenido vía API. Next.js renderiza frontend.
- SSR, SSG e ISR: decide si renderizas en build time (getStaticProps), en cada request (getServerSideProps) o con revalidación incremental (ISR con revalidate).
- CORS: si el front y WP están en dominios distintos, asegúrate de permitir orígenes y métodos necesarios.
- Autenticación: para acciones protegidas (crear posts, comentarios no públicos) necesitas autenticación (JWT o cookies).
Ejemplo básico: obtener posts en getStaticProps
Este patrón es ideal para un blog de contenido que no cambia constantemente. getStaticProps hace fetch a la API en build time. Si quieres actualizaciones, usa revalidate (ISR).
// pages/index.js (Next.js) // Fetch de posts desde WordPress en getStaticProps export async function getStaticProps() { const WP_BASE = https://tudominio.com/wp-json/wp/v2 const res = await fetch({WP_BASE}/posts?_embedper_page=10) if (!res.ok) { return { props: { posts: [] }, revalidate: 60 } } const posts = await res.json() return { props: { posts }, revalidate: 60 // ISR: revalida cada 60s } } export default function Home({ posts }) { return ({posts.map(p => ( ) }))}
Detalles importantes del ejemplo
- El parámetro _embed inserta datos relacionados (media, author) en la respuesta para evitar múltiples requests.
- Campos HTML en la API vienen como strings con rendered — usa dangerouslySetInnerHTML con cuidado y sanitiza si no confías en el contenido.
ISR y preview (previsualización de borradores)
Para usar previsualización de entradas privadas o drafts necesitas autenticación y una ruta de preview en Next.js que valide el token de preview de WordPress y luego haga fetch al post. La combinación típica:
- Activar la API de preview en WordPress (la funcionalidad nativa webs).
- Crear una página API en Next.js que acepte el token de preview y setee las cookies de preview o redireccione a la ruta con un flag que incremente la revalidación.
getServerSideProps: cuando necesitas datos por request
Usa getServerSideProps para contenido personalizado por usuario o que deba estar siempre actualizado en cada request (por ejemplo contenido dependiente de sesión).
// pages/profile.js export async function getServerSideProps(context) { // Supongamos que hay una cookie con token de WP o similar const token = context.req.cookies[wp_token] null const WP_BASE = https://tudominio.com/wp-json/wp/v2 const headers = token ? { Authorization: Bearer {token} } : {} const res = await fetch({WP_BASE}/posts?author=me_embed, { headers }) const posts = await res.json() return { props: { posts } } }
SWR es una librería excelente para datos que pueden mutar en cliente y para revalidación automática.
// components/LatestPosts.js import useSWR from swr const fetcher = url => fetch(url).then(r => r.json()) export default function LatestPosts() { const { data: posts, error } = useSWR(/api/wp/posts, fetcher, { refreshInterval: 30000 }) if (error) returnErrorif (!posts) returnCargando...return (
-
{posts.map(p =>
- {p.title.rendered} )}
En este ejemplo se usa una API route de Next.js (/api/wp/posts) para ocultar el origen y añadir caché o headers si es necesario.
Ejemplo: API Route en Next.js que hace proxy a WordPress
// pages/api/wp/posts.js export default async function handler(req, res) { const WP_BASE = https://tudominio.com/wp-json/wp/v2 const apiRes = await fetch({WP_BASE}/posts?_embedper_page=10) if (!apiRes.ok) return res.status(502).json({ error: Bad gateway }) const data = await apiRes.json() // Puedes transformar datos aquí res.setHeader(Cache-Control, s-maxage=60, stale-while-revalidate=120) return res.status(200).json(data) }
Imágenes de WordPress y Next/Image
WordPress devuelve URLs para imágenes en el objeto _embedded -> media. Para usar next/image debes añadir el dominio de WordPress en next.config.js:
// next.config.js module.exports = { images: { domains: [tudominio.com, cdn.tudominio.com], }, }
Luego mapear el tamaño deseado (por ejemplo medium, full) desde response.media_details.sizes o desde source_url:
// uso de next/image import Image from next/image
Autenticación: JWT (ejemplo práctico)
Para crear, actualizar o borrar recursos necesitas autenticación. Un enfoque común es usar un plugin de JWT (por ejemplo: JWT Authentication for WP REST API).
- Instalar y configurar plugin JWT en WP. Define la clave secreta en wp-config.php:
// wp-config.php define(JWT_AUTH_SECRET_KEY, tu_clave_super_secreta_y_larga)
- Obtener token:
# POST /wp-json/jwt-auth/v1/token curl -X POST https://tudominio.com/wp-json/jwt-auth/v1/token -d username=tuuserpassword=tucontrasena
// Respuesta típica { token: eyJ0eXAiOiJKV1QiLCJh..., user_email: admin@tudominio.com, user_display_name: Admin }
- Usar el token desde Next.js al hacer requests protegidos:
// Crear un post desde Next.js (cliente o API route) const token = eyJ... // obtenido tras login await fetch(https://tudominio.com/wp-json/wp/v2/posts, { method: POST, headers: { Authorization: Bearer {token}, Content-Type: application/json }, body: JSON.stringify({ title: Mi post creado desde Next, content: Contenido del post, status: publish }) })
Crear endpoints personalizados en WordPress
Si necesitas devolver estructuras personalizadas o incluir ACF fields, registra rutas propias con register_rest_route en el archivo de funciones del tema o plugin.
// functions.php o plugin personalizado add_action(rest_api_init, function() { register_rest_route(mi-plugin/v1, /posts-breve, array( methods => GET, callback => mi_posts_breve, permission_callback => __return_true )) }) function mi_posts_breve(request) { args = array(post_type => post, posts_per_page => 10) q = new WP_Query(args) items = array() while (q->have_posts()) { q->the_post() items[] = array( id => get_the_ID(), title => get_the_title(), excerpt => get_the_excerpt(), acf => function_exists(get_fields) ? get_fields(get_the_ID()) : null ) } wp_reset_postdata() return rest_ensure_response(items) }
Manejo de CORS
Si el front y WP están en dominios distintos, añade headers CORS desde WordPress. Un ejemplo simple (con cuidado):
// functions.php add_action(init, function() { header(Access-Control-Allow-Origin: https://mi-front.com) header(Access-Control-Allow-Methods: GET, POST, OPTIONS) header(Access-Control-Allow-Headers: Authorization, Content-Type) })
Nota: para producción, define orígenes explícitos y no uses . Para peticiones preflight OPTIONS asegúrate de responder correctamente si usas nginx/Apache.
ACF (Advanced Custom Fields)
Si tu WP usa ACF, activa la opción Show in REST API o usa el plugin ACF to REST API para exponer campos personalizados. También puedes exponerlos desde un endpoint personalizado (ver ejemplo de PHP más arriba).
Seguridad y buenas prácticas
- No expongas claves en el cliente. Realiza acciones sensibles desde API routes del servidor Next.js cuando sea posible.
- Usa HTTPS siempre.
- Valida y sanitiza datos en WordPress antes de guardarlos.
- Implementa rate limiting si la API pública puede ser abusada.
- Cachea respuestas públicas con headers y CDN (Cloudflare, Fastly) y usa incremental static regeneration para escalar.
Rendimiento
- Usa _embed para reducir requests pero evita respuestas demasiado pesadas negocia qué campos necesitas usando el parámetro _fields.
- Cachea en el borde (CDN) y usa s-maxage en API routes.
- Optimiza imágenes en WP (webp, tamaños) y usa next/image con dominios permitidos.
Errores comunes y cómo resolverlos
- 403/401 en POST/PUT: revisa autenticación y permisos del usuario verifica Authorization header y CORS.
- Respuesta vacía o HTML en vez de JSON: puede que WordPress haga redirect a login prueba la ruta directamente en el navegador y mira headers.
- Problemas de CORS: añade los headers apropiados desde WP o configura el servidor (nginx/apache).
- Paginación: usa parámetros page y per_page fíjate en headers que devuelven total y totalPages.
Resumen práctico: checklist para lanzar
- Decide estrategia: SSG (getStaticProps) ISR, SSR (getServerSideProps) o cliente (SWR).
- Comprueba endpoints públicos (/wp-json/wp/v2/posts?_embed).
- Configura next.config.js para dominios de imágenes.
- Configura autenticación segura si necesitas escribir datos (JWT o cookies).
- Implementa caching y headers apropiados en API routes o en WordPress.
- Si necesitas campos complejos, expónlos con ACF o endpoints personalizados.
Conclusión
Consumir WordPress desde Next.js mediante la REST API es un flujo flexible y potente: permite separar CMS y frontend, aprovechar ISR para rendimiento y proporcionar experiencias modernas con React. Con los ejemplos y pautas mostradas aquí puedes implementar un flujo completo: lectura pública, previsualización, creación/edición autenticada y endpoints personalizados. Adapta los snippets a tus dominios y credenciales, y aplica las medidas de seguridad y caché adecuadas antes de producción.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |