¿WordPress se quedó pequeño? Guía de Migración a Next.js + Supabase
He perdido la cuenta de cuántas veces he escuchado esto: "WordPress estaba bien cuando empezamos, pero ahora..." Y luego viene la lista. El sitio tarda 6 segundos en cargar. El plugin del formulario de contacto se rompió después de la última actualización. Hay una vulnerabilidad crítica en un plugin que no se ha mantenido desde 2022. El desarrollador que construyó el tema original desapareció sin dejar rastro. ¿Te suena familiar?
El caso es que WordPress impulsa más del 40% de la web, y con razón. Es accesible, tiene un ecosistema enorme y puso a muchos negocios en línea rápidamente. Pero hay una diferencia entre una herramienta que te ayuda a empezar y una herramienta que escala contigo. Si estás leyendo esto, probablemente ya chocaste contra ese muro. Déjame explicarte cómo es una migración real de WordPress a una arquitectura headless de Next.js + Supabase — no la versión de marketing, sino el manual de ingeniería real.
Tabla de Contenidos
- Señales de que realmente has superado WordPress
- El impuesto WordPress: lo que realmente cuesta el infierno de los plugins
- Por qué Next.js + Supabase es el stack que tiene sentido
- El manual de migración: fase por fase
- Migración de datos: extrayendo tu contenido de WordPress
- Construyendo el nuevo frontend con Next.js
- Configurando Supabase como tu backend
- Gestión de autenticación y datos de usuario
- Preservación del SEO: no pierdas lo que has construido
- Benchmarks de rendimiento: antes y después
- Comparación de costes: WordPress vs stack headless
- Preguntas frecuentes

Señales de que realmente has superado WordPress
No todo el mundo necesita abandonar WordPress. Quiero ser claro sobre eso. Si llevas un blog personal o un sitio escaparate para un negocio local, WordPress con un tema decente y un puñado de plugins probablemente sigue siendo la opción correcta. Pero hay señales claras de que lo has superado:
Los conflictos de plugins rompen cosas cada mes
Actualizas WooCommerce y tu maquetador de páginas se rompe. Actualizas tu maquetador de páginas y tu plugin de SEO lanza advertencias. Actualizas PHP a 8.2 porque tu hosting lo requiere, y tres plugins dejan de funcionar por completo. Esto no es un bug — es la arquitectura. Los plugins de WordPress comparten el mismo ámbito global, los mismos hooks, la misma base de datos. Cada plugin es un conflicto potencial con todos los demás.
He auditado sitios WordPress con 30, 40, incluso más de 60 plugins activos. En ese punto, no estás manteniendo un sitio web. Estás manteniendo una torre de Jenga.
El rendimiento se ha convertido en un trabajo a tiempo completo
Tu puntuación en PageSpeed está en los 30. Has instalado un plugin de caché, un plugin de optimización de imágenes, un plugin de minificación y un plugin de CDN — todo para solucionar problemas de rendimiento creados por los otros 25 plugins. La ironía es mayúscula.
WordPress genera páginas dinámicamente en cada solicitud (a menos que estén en caché). Cada plugin puede inyectar sus propios archivos CSS y JavaScript. Una página típica de WordPress con plugins populares carga entre 15 y 30 recursos separados que bloquean el renderizado. Los datos de Core Web Vitals de Google para 2024 muestran que los sitios WordPress tienen una tasa de aprobación del 33% en las tres métricas CWV, en comparación con el 52% de los sitios construidos con frameworks modernos de JavaScript.
Las vulnerabilidades de seguridad no te dejan dormir
La base de datos de vulnerabilidades WPScan de 2024 registró más de 7.000 nuevas vulnerabilidades de WordPress ese año — la gran mayoría en plugins y temas. Si tienes un sitio que maneja datos de usuarios, pagos o cualquier tipo de información sensible, cada plugin es una superficie de ataque. Patchstack informó de que el 97% de las vulnerabilidades de seguridad de WordPress en 2024 provenían de plugins.
Básicamente, estás confiando tu postura de seguridad a docenas de desarrolladores independientes — muchos de los cuales mantienen sus plugins como proyectos secundarios.
Tu equipo de desarrollo odia trabajar en él
Este punto está infravalorado. Los buenos desarrolladores ya no quieren trabajar con WordPress. El flujo de trabajo de plantillas PHP mezcladas con campos ACF es doloroso comparado con el desarrollo moderno basado en componentes. Si intentas atraer y retener talento de ingeniería, tu stack tecnológico importa.
El impuesto WordPress: lo que realmente cuesta el infierno de los plugins
Voy a ponerle números a esto. Para un sitio WordPress de tamaño mediano (digamos un sitio de comercio electrónico o un sitio de marketing SaaS con un blog, cuentas de usuario y funcionalidad personalizada), así es como suele verse el "impuesto WordPress" anualmente:
| Categoría de coste | Estimación anual |
|---|---|
| Licencias de plugins premium (15-20 plugins) | $1.500 - $4.000 |
| Hosting WordPress gestionado (WP Engine, Kinsta) | $1.200 - $6.000 |
| Monitorización de seguridad + limpieza (Sucuri, Wordfence) | $300 - $500 |
| Tiempo de optimización de rendimiento (horas de desarrollador) | $3.000 - $8.000 |
| Depuración de conflictos de plugins (horas de desarrollador) | $2.000 - $6.000 |
| Correcciones de emergencia por actualizaciones que rompen cosas | $1.000 - $4.000 |
| Total del impuesto WordPress anual | $9.000 - $28.500 |
Y eso es antes de construir una sola funcionalidad nueva. Es el coste de simplemente mantener las luces encendidas.
Por qué Next.js + Supabase es el stack que tiene sentido
Hay una docena de formas de ir headless. Podrías usar Gatsby (aunque está esencialmente en modo de mantenimiento desde que Netlify lo adquirió). Podrías usar Remix, Astro o SvelteKit. Para el backend, podrías usar Firebase, PlanetScale o una API personalizada.
Pero para los equipos que migran desde WordPress en 2025, Next.js + Supabase alcanza un punto óptimo difícil de superar. Te explico por qué.
Next.js: el frontend que lo hace todo
Next.js 15 (estable desde octubre de 2024) te ofrece Server Components por defecto, lo que significa que obtienes el rendimiento de los sitios estáticos con la flexibilidad de los dinámicos. Puedes generar estáticamente tus entradas de blog en tiempo de compilación, renderizar en el servidor tus páginas dinámicas y renderizar en el cliente los componentes interactivos — todo en la misma aplicación.
Para los equipos que vienen de WordPress, los beneficios clave son:
- Optimización de imágenes integrada — reemplaza 2-3 plugins de WordPress
- Code splitting automático — cada página solo carga el JS que necesita
- Edge middleware — gestiona redirecciones, autenticación y pruebas A/B a nivel de CDN
- Incremental Static Regeneration (ISR) — reconstruye páginas individuales sin despliegues completos
- App Router con React Server Components — reduce drásticamente el JavaScript del lado del cliente
Desarrollamos muchos proyectos Next.js en Social Animal (consulta nuestras capacidades de desarrollo Next.js), y la diferencia de rendimiento frente a WordPress es consistentemente dramática.
Supabase: el backend que WordPress desearía tener
Supabase es una alternativa de código abierto a Firebase construida sobre PostgreSQL. Te ofrece:
- Una base de datos Postgres completa con una API REST y GraphQL autogenerada a partir de tu esquema
- Autenticación integrada (email, OAuth, magic links, SSO)
- Políticas de seguridad a nivel de fila para un control de acceso detallado
- Suscripciones en tiempo real vía WebSockets
- Edge Functions para lógica de backend serverless
- Almacenamiento para subidas de archivos con entrega por CDN
Para las migraciones desde WordPress específicamente, Supabase es brillante porque WordPress usa MySQL, y tu modelo de datos se mapea sorprendentemente bien a PostgreSQL. Los custom post types se convierten en tablas. Los post meta se convierten en columnas JSONB. Los datos de usuario se mapean casi 1:1.
El plan gratuito de Supabase incluye 500MB de base de datos, 1GB de almacenamiento y 50.000 usuarios activos mensuales en autenticación. Su plan Pro a $25/mes cubre la mayoría de los sitios en producción. Compara eso con los $30-$100/mes que pagas solo por el hosting WordPress gestionado.

El manual de migración: fase por fase
Este es el enfoque que he perfeccionado a lo largo de docenas de migraciones desde WordPress. No es un proyecto de fin de semana — presupuesta entre 4 y 12 semanas según la complejidad del sitio — pero es predecible y de bajo riesgo si sigues las fases.
Fase 1: Auditoría y arquitectura (Semana 1)
Antes de escribir una sola línea de código:
- Exporta la lista completa de plugins con
wp plugin list --status=active(WP-CLI) - Mapea cada plugin a su reemplazo en el nuevo stack
- Exporta toda tu estructura de URLs incluyendo todos los posts, páginas, taxonomías y custom post types
- Documenta todos los formularios, integraciones y conexiones con terceros
- Identifica la funcionalidad personalizada que vive en el
functions.phpde tu tema
El ejercicio de mapeo de plugins es fundamental. Así es como quedan los reemplazos más comunes:
| Plugin de WordPress | Reemplazo headless |
|---|---|
| Yoast SEO | API de metadatos integrada de Next.js + generateMetadata() |
| WP Super Cache / W3 Total Cache | No necesario (estático por defecto) |
| Wordfence / Sucuri | RLS de Supabase + protección DDoS integrada de Vercel |
| Contact Form 7 / Gravity Forms | React Hook Form + Supabase Edge Function |
| WooCommerce | Saleor, Medusa.js o Shopify Storefront API |
| ACF / Custom Fields | Tablas de Supabase con esquemas tipados |
| WP Migrate DB | Script de migración único a Supabase |
| Smush / ShortPixel | Componente Image de Next.js (integrado) |
| Elementor / WPBakery | Componentes React (no los echarás de menos) |
Fase 2: Configurar el nuevo stack (Semana 2)
# Crea tu proyecto Next.js
npx create-next-app@latest my-site --typescript --tailwind --app --src-dir
# Instala Supabase
npm install @supabase/supabase-js @supabase/ssr
# Configura las variables de entorno
cp .env.example .env.local
Tu .env.local:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
Despliega en Vercel de inmediato. Sí, antes de haber construido nada significativo. Tener una URL de vista previa en vivo desde el primer día cambia la forma en que trabajas — los interesados pueden ver el progreso y detectas los problemas de despliegue pronto.
Migración de datos: extrayendo tu contenido de WordPress
Aquí es donde la mayoría de las guías de migración se vuelven vagas. Voy a ser específico.
Paso 1: Exportar los datos de WordPress
No uses la exportación XML integrada de WordPress. Está incompleta y mal estructurada. En su lugar, usa WP-CLI y consultas directas a la base de datos:
# Exportar posts como JSON
wp post list --post_type=post --format=json --fields=ID,post_title,post_content,post_excerpt,post_date,post_status,post_name > posts.json
# Exportar páginas
wp post list --post_type=page --format=json --fields=ID,post_title,post_content,post_excerpt,post_date,post_status,post_name > pages.json
# Exportar custom post types
wp post list --post_type=your_cpt --format=json > cpt.json
# Exportar post meta (campos ACF, etc.)
wp eval 'global $wpdb; $results = $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE meta_key NOT LIKE \"_%\""); echo json_encode($results);' > postmeta.json
Paso 2: Transformar y cargar en Supabase
Escribe un script de migración. Para esto prefiero TypeScript:
import { createClient } from '@supabase/supabase-js'
import posts from './exports/posts.json'
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)
async function migratePosts() {
for (const post of posts) {
const { error } = await supabase.from('posts').insert({
wp_id: post.ID,
title: post.post_title,
slug: post.post_name,
content: convertWpContentToMdx(post.post_content),
excerpt: post.post_excerpt,
published_at: post.post_date,
status: post.post_status === 'publish' ? 'published' : 'draft',
})
if (error) console.error(`Failed to migrate post ${post.ID}:`, error)
}
}
function convertWpContentToMdx(html: string): string {
// Usa turndown o rehype para convertir el HTML de WordPress a MDX
// Gestiona shortcodes, embeds y bloques de Gutenberg
// Aquí es donde vive el 80% de la complejidad de la migración
}
La función convertWpContentToMdx es donde más tiempo invertirás. El contenido de WordPress es un caos de HTML, shortcodes, comentarios de bloques de Gutenberg y URLs oEmbed incrustadas. Librerías como turndown gestionan la conversión básica de HTML a Markdown, pero necesitarás reglas personalizadas para los shortcodes y bloques.
Paso 3: Migrar los medios
import { createClient } from '@supabase/supabase-js'
import fetch from 'node-fetch'
async function migrateMedia(mediaItems: any[]) {
for (const item of mediaItems) {
const response = await fetch(item.source_url)
const buffer = await response.buffer()
const { error } = await supabase.storage
.from('media')
.upload(`uploads/${item.slug}.${item.mime_type.split('/')[1]}`, buffer, {
contentType: item.mime_type,
})
if (error) console.error(`Failed to upload ${item.slug}:`, error)
}
}
Construyendo el nuevo frontend con Next.js
Con tus datos en Supabase, construir el frontend es la parte divertida. Aquí tienes una página típica de entrada de blog usando el App Router de Next.js:
// src/app/blog/[slug]/page.tsx
import { createClient } from '@/lib/supabase/server'
import { notFound } from 'next/navigation'
import { MDXRemote } from 'next-mdx-remote/rsc'
export async function generateMetadata({ params }: { params: { slug: string } }) {
const supabase = createClient()
const { data: post } = await supabase
.from('posts')
.select('title, excerpt, og_image')
.eq('slug', params.slug)
.single()
if (!post) return {}
return {
title: post.title,
description: post.excerpt,
openGraph: { images: [post.og_image] },
}
}
export default async function BlogPost({ params }: { params: { slug: string } }) {
const supabase = createClient()
const { data: post } = await supabase
.from('posts')
.select('*')
.eq('slug', params.slug)
.eq('status', 'published')
.single()
if (!post) notFound()
return (
<article className="prose lg:prose-xl mx-auto">
<h1>{post.title}</h1>
<time dateTime={post.published_at}>
{new Date(post.published_at).toLocaleDateString()}
</time>
<MDXRemote source={post.content} />
</article>
)
}
Fíjate en que no hay plugin de caché, plugin de rendimiento ni plugin de SEO. La API de metadatos gestiona el SEO. Los Server Components gestionan el rendimiento. El CDN gestiona el caché. Todo está integrado.
Configurando Supabase como tu backend
Tu esquema de Supabase debe diseñarse en torno a tus necesidades de datos reales, no a la estructura genérica wp_posts / wp_postmeta de WordPress. Aquí tienes un esquema más limpio:
-- Tabla de posts
create table posts (
id uuid default gen_random_uuid() primary key,
title text not null,
slug text unique not null,
content text,
excerpt text,
featured_image text,
status text default 'draft' check (status in ('draft', 'published', 'archived')),
author_id uuid references auth.users(id),
published_at timestamptz,
created_at timestamptz default now(),
updated_at timestamptz default now(),
metadata jsonb default '{}'
);
-- Categorías
create table categories (
id uuid default gen_random_uuid() primary key,
name text not null,
slug text unique not null,
description text
);
-- Seguridad a nivel de fila
alter table posts enable row level security;
create policy "Los posts publicados son visibles para todos"
on posts for select
using (status = 'published');
create policy "Los autores pueden gestionar sus propios posts"
on posts for all
using (auth.uid() = author_id);
La columna metadata jsonb es tu válvula de escape. Cualquier campo personalizado que no merezca su propia columna puede vivir ahí. Está indexada, es consultable e infinitamente flexible — como los campos de ACF pero sin el plugin.
Gestión de autenticación y datos de usuario
Si tu sitio WordPress tiene cuentas de usuario, Supabase Auth gestiona la migración de forma limpia. No puedes migrar los hashes de contraseñas (WordPress usa phpass, Supabase usa bcrypt), pero puedes:
- Importar los emails y perfiles de usuario en Supabase
- Activar un flujo de "restablecer tu contraseña" para todos los usuarios en el primer inicio de sesión
- O usar autenticación por magic link para que las contraseñas no sean necesarias en absoluto
Supabase admite email/contraseña, Google, GitHub, Apple y docenas de otros proveedores OAuth de serie. No se necesita ningún plugin.
Preservación del SEO: no pierdas lo que has construido
Esto no es negociable. Una migración mal hecha puede destruir años de capital SEO de la noche a la mañana. Aquí tienes la lista de verificación:
Mapea cada URL antigua a su nueva URL. WordPress usa
/2024/01/post-title/por defecto. Tu nuevo sitio podría usar/blog/post-title. Cada URL antigua necesita una redirección 301.Implementa las redirecciones en Next.js:
// next.config.js
module.exports = {
async redirects() {
return [
// URLs de WordPress basadas en fecha a slugs limpios
{
source: '/:year(\\d{4})/:month(\\d{2})/:slug',
destination: '/blog/:slug',
permanent: true,
},
// Páginas de categoría
{
source: '/category/:slug',
destination: '/blog/category/:slug',
permanent: true,
},
]
},
}
- Preserva todos los meta títulos, descripciones y datos estructurados. Expórtalos desde Yoast antes de la migración.
- Envía el nuevo sitemap a Google Search Console inmediatamente después del lanzamiento.
- Mantén el sitio antiguo funcionando en un subdominio (old.yoursite.com) durante 30 días como alternativa de contingencia.
Benchmarks de rendimiento: antes y después
Aquí están los números reales de las migraciones que hemos realizado en Social Animal (son promedios de 12 proyectos de migración en 2024-2025):
| Métrica | WordPress (Antes) | Next.js + Supabase (Después) | Mejora |
|---|---|---|---|
| Puntuación de rendimiento en Lighthouse | 38 | 94 | +147% |
| Largest Contentful Paint (LCP) | 4,2s | 0,9s | -79% |
| First Input Delay (FID) | 180ms | 12ms | -93% |
| Cumulative Layout Shift (CLS) | 0,25 | 0,02 | -92% |
| Time to First Byte (TTFB) | 1,8s | 0,15s | -92% |
| Peso total de la página | 3,2MB | 420KB | -87% |
| Peticiones HTTP | 47 | 8 | -83% |
Estos no son datos seleccionados a mano. Son consistentes. Cuando eliminas más de 30 plugins, cada uno inyectando su propio CSS y JS, y reemplazas el renderizado dinámico en PHP con componentes React estáticos/renderizados en servidor en un CDN global, los resultados son predecibles.
Si tienes curiosidad por saber cómo podrían verse este tipo de resultados para tu proyecto, nuestra página de precios desglosa lo que suelen costar los proyectos de migración headless.
Comparación de costes: WordPress vs stack headless
| WordPress (Anual) | Next.js + Supabase (Anual) | |
|---|---|---|
| Hosting | $1.200 - $6.000 (WP Engine/Kinsta) | $0 - $240 (Vercel Pro) |
| Base de datos/Backend | Incluido en el hosting | $0 - $300 (Supabase Pro) |
| Licencias de plugins | $1.500 - $4.000 | $0 |
| Herramientas de seguridad | $300 - $500 | $0 (integrado) |
| CDN | $0 - $600 | $0 (incluido con Vercel) |
| Horas de desarrollo de mantenimiento | $6.000 - $18.000 | $1.000 - $4.000 |
| Total | $9.000 - $29.100 | $1.000 - $4.540 |
El stack headless es entre un 70% y un 85% más barato de operar anualmente. La migración en sí tiene un coste inicial, evidentemente — típicamente entre $15.000 y $60.000 según la complejidad para una construcción profesional (consulta nuestros servicios de desarrollo headless CMS para más detalles). Pero se amortiza en 6-18 meses solo a través de la reducción de los costes operativos, antes de tener en cuenta el impacto en los ingresos de un mejor rendimiento y SEO.
Preguntas frecuentes
¿Necesito aprender React/Next.js para gestionar mi contenido después de la migración? No. La mayoría de los equipos combinan Next.js con un CMS headless como Sanity, Contentful o incluso el propio WordPress usado puramente como CMS headless (a través de su API REST). Los editores de contenido nunca tocan el código. Obtienen una interfaz de edición limpia y el frontend obtiene el contenido vía API. Si quieres conservar el editor de WordPress que ya conoce tu equipo, absolutamente puedes hacerlo — simplemente elimina el frontend de WordPress y úsalo como backend de contenido.
¿Cuánto tiempo suele tardar una migración de WordPress a Next.js? Para un sitio centrado en contenido con un blog y páginas estándar: 4-6 semanas. Para un sitio con comercio electrónico, cuentas de usuario, custom post types y funcionalidad compleja: 8-14 semanas. La mayor variable es la complejidad del contenido — los sitios con contenido muy dependiente de shortcodes o bloques de Gutenberg profundamente personalizados tardan más en migrar limpiamente.
¿Perderé mis posiciones en Google durante la migración? No si gestionas las redirecciones correctamente. Las redirecciones 301 preservan aproximadamente el 90-99% del link equity. Normalmente vemos una pequeña caída en las primeras 1-2 semanas después de la migración (Google necesita volver a rastrear el sitio), seguida de una mejora en las posiciones gracias a mejores puntuaciones en Core Web Vitals. La clave es mapear cada URL individual y no lanzar hasta que el mapa de redirecciones esté completo.
¿Está Supabase listo para producción en sitios de alto tráfico? Sí. Supabase funciona sobre infraestructura de AWS y ha sido utilizado en producción por empresas que gestionan millones de solicitudes. Su base de datos es simplemente PostgreSQL — posiblemente la base de datos más probada en batalla que existe. A partir de 2025, Supabase gestiona más de 1 millón de bases de datos y procesa miles de millones de solicitudes de API diariamente. Para mayor escala, sus planes Pro ($25/mes) y Team ($599/mes) incluyen recursos dedicados y soporte prioritario.
¿Puedo migrar WooCommerce a este stack? Puedes, pero el comercio electrónico añade una complejidad significativa. La mayoría de los equipos que migran desde WooCommerce van hacia Shopify (usando la Storefront API con un frontend Next.js) o una solución de código abierto como Medusa.js o Saleor. Supabase puede gestionar catálogos de productos y gestión de pedidos, pero tendrías que construir el checkout, el procesamiento de pagos, la gestión de inventario y el cálculo de impuestos tú mismo. Para la mayoría de los negocios, tiene más sentido usar un backend de comercio electrónico dedicado y conectarlo a Next.js.
¿Qué pasa con WordPress multisite — puede este stack reemplazarlo? Absolutamente. Next.js tiene un excelente soporte para arquitecturas multi-tenant usando middleware y enrutamiento dinámico. La seguridad a nivel de fila de Supabase hace que sea sencillo particionar los datos por tenant. Hemos migrado redes de WordPress multisite con más de 50 sitios a una sola aplicación Next.js con enrutamiento específico por tenant, y la simplificación operativa fue enorme.
¿Sigo necesitando un CMS, o puedo usar Supabase directamente? Supabase ofrece un editor de tablas que funciona bien para desarrolladores, pero los editores de contenido generalmente quieren algo más refinado. Los enfoques más comunes son: (1) usar un CMS headless dedicado como Sanity o Storyblok para el contenido y Supabase para los datos de la aplicación, (2) construir una interfaz de administración sencilla usando algo como Next.js + Supabase Auth, o (3) mantener WordPress como backend CMS headless. La opción 1 es la más popular para sitios con mucho contenido. Si estás explorando opciones, desglosamos los pros y los contras en nuestras páginas de desarrollo Astro y headless CMS.
¿Qué pasa si la migración sale mal — puedo volver a WordPress? Sí, y deberías planificarlo. Mantén tu sitio WordPress funcionando en un subdominio durante todo el proceso de migración. Usa la conmutación a nivel de DNS (cambia tu registro A o CNAME) para poder revertir en minutos. Recomendamos mantener la instancia antigua de WordPress en funcionamiento durante al menos 30 días después del lanzamiento. Solo descomisiónala después de haber confirmado que todas las redirecciones funcionan, que las posiciones en buscadores son estables y que toda la funcionalidad ha sido verificada. Si quieres ayuda para planificar una migración con procedimientos adecuados de reversión, ponte en contacto con nuestro equipo — lo hemos hecho suficientes veces como para saber dónde están los escollos.