Seu WordPress carrega 487 kilobytes a cada página — assets de tema, scripts de plugin, dependências jQuery empilhadas três camadas de profundidade. Você vê scores de performance do Lighthouse travarem nos 40s enquanto seus concorrentes com sites Next.js ficam acima de você com conteúdo idêntico. A migração para Next.js e Vercel soa limpa em teoria: exportar conteúdo, conectar um headless CMS, fazer deploy. Na prática, acompanhei doze dessas migrações em três anos. Quatro foram entregues em menos de duas semanas. Oito ficaram paradas por meses porque os times perderam o que WordPress estava silenciosamente tratando — redirects, otimização de imagens, sitemaps XML, injeção de meta — antes de eliminar a instalação. A diferença entre uma cutover tranquila e um rollback às 2 da manhã quase sempre vem para uma coisa: auditar o que WordPress realmente faz pelo seu site antes de desligar a instalação.

Este guia é tudo o que desejo que alguém tivesse me entregue antes da minha primeira migração. Cobriremos a jornada completa: avaliar se você deveria sequer migrar, escolher seu headless CMS, mover conteúdo, reconstruir templates, lidar com SEO sem perder rankings, e fazer deploy no Vercel com uma configuração que não desabará sob picos de tráfego.

Vamos lá.

WordPress to Next.js Migration on Vercel: A 2026 Guide

Índice

Por que migrar do WordPress para Next.js em 2026?

Sejamos honestos — WordPress ainda alimenta aproximadamente 40% da web em 2026. Não vai desaparecer. Mas as razões para sair ficaram mais convincentes:

Teto de performance. Mesmo com plugins de caching agressivo (WP Rocket, W3 Total Cache), a maioria dos sites WordPress bate em um muro ao redor de 70-80 em scores de performance do Lighthouse. Bloat de plugin, PHP com render-blocking, e queries de banco de dados em cada carregamento de página criam overhead que nenhuma quantidade de otimização pode eliminar completamente.

Superfície de segurança. WordPress teve 149 vulnerabilidades documentadas em 2025 entre core e plugins populares. Cada plugin é um vetor de ataque. Cada atualização de tema é uma quebra potencial. Se você está rodando WooCommerce, a superfície de ataque dobra.

Experiência do desenvolvedor. Se seu time conhece React, construir em templates PHP se sente como escrever com sua mão não dominante. App Router do Next.js 15, Server Components, e caching integrado oferecem um workflow de desenvolvimento moderno que WordPress não consegue acompanhar.

Custo em escala. Hosting WordPress gerenciado (WP Engine, Kinsta) custa $30-$300/mês para performance decente. Plano Pro do Vercel em $20/usuário/mês com edge functions e escala automática geralmente custa menos enquanto performa melhor.

Dito isto — não migre apenas porque é tendência. Se seu site é um blog simples com 50 posts e seu cliente o atualiza semanalmente via admin do WordPress, uma migração pode criar mais problemas do que resolve. Os melhores candidatos para migração são:

  • Sites com 500+ páginas que precisam de melhor performance
  • Times que querem desenvolvimento baseado em componentes
  • Sites onde conflitos de plugin estão causando nightmares de manutenção
  • Sites de e-commerce batendo nos limites de performance do WooCommerce
  • Sites de marketing que precisam de A/B testing e personalização na edge

Auditoria Pré-Migração: O Que WordPress Está Realmente Fazendo

Aqui é onde a maioria das migrações dá errado. As pessoas pensam que estão migrando um blog, mas WordPress está realmente tratando contact forms, redirects, otimização de imagens, search, comentários, autenticação, cron jobs, e quinze outras coisas enterradas em configurações de plugin.

Antes de escrever uma única linha de código Next.js, documente tudo:

Inventário de Plugins

Exporte sua lista de plugins e categorize cada um:

wp plugin list --status=active --format=csv > active-plugins.csv

Para cada plugin, responda: O que isso faz, e o que o substitui no ecossistema Next.js?

Plugin WordPress Função Substituição Next.js
Yoast SEO Meta tags, sitemaps, schema next-seo + custom sitemap.xml route
WP Rocket Caching, minification Vercel Edge Cache + built-in Next.js
Contact Form 7 Tratamento de form React Hook Form + API route ou Formspree
Wordfence Segurança Não necessário (sem superfície de admin)
WPML Multilíngue next-intl ou built-in i18n routing
WooCommerce E-commerce Shopify Storefront API ou Saleor
Advanced Custom Fields Modelos de conteúdo customizado Content modeling do seu headless CMS
Redirection URL redirects redirects do next.config.js ou config Vercel
WP Cron Tarefas agendadas Vercel Cron Jobs ou serviço separado
Imagify Otimização de imagem next/image com Vercel Image Optimization

Inventário de Conteúdo

Contabilize e categorize seu conteúdo:

SELECT post_type, post_status, COUNT(*) 
FROM wp_posts 
GROUP BY post_type, post_status;

Não esqueça: custom post types, taxonomy terms, user profiles, estruturas de menu, configurações de widget, e option values. Aquele site WordPress "simples" provavelmente tem mais tipos de conteúdo do que você pensa.

URL Mapping

Exporte cada URL. Cada uma mesmo. Use Screaming Frog ou um crawl de sitemap simples:

curl -s https://yoursite.com/sitemap_index.xml | \
grep -oP '<loc>\K[^<]+' | \
xargs -I {} curl -s {} | \
grep -oP '<loc>\K[^<]+' > all-urls.txt

Este arquivo é ouro. Você o usará para mapeamento de redirect, preservação de SEO, e testes de QA após migração.

WordPress to Next.js Migration on Vercel: A 2026 Guide - architecture

Escolhendo Seu Backend de Headless CMS

Você precisa de um lugar para armazenar e gerenciar conteúdo. Os três caminhos mais comuns em 2026:

Opção 1: WordPress como Headless CMS

Sim, você pode manter WordPress como backend e usar Next.js como frontend. WPGraphQL (agora em v2.1) torna isso surpreendentemente viável. Seus editores mantêm a interface admin familiar. Você consegue um frontend moderno.

// lib/wordpress.js
const API_URL = process.env.WORDPRESS_GRAPHQL_URL;

export async function getPostBySlug(slug) {
  const res = await fetch(API_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query: `
        query PostBySlug($slug: ID!) {
          post(id: $slug, idType: SLUG) {
            title
            content
            date
            featuredImage {
              node {
                sourceUrl
                altText
              }
            }
            seo {
              title
              metaDesc
              opengraphImage {
                sourceUrl
              }
            }
          }
        }
      `,
      variables: { slug },
    }),
    next: { revalidate: 60 },
  });
  const json = await res.json();
  return json.data.post;
}

O downside? Você ainda mantém uma instalação WordPress. Atualizações de segurança, gerenciamento de versão PHP, backups de banco de dados — tudo fica no seu prato. E você ainda está pagando por hosting WordPress.

Opção 2: Headless CMS Propósito-Construído

Isso é o que recomendo para a maioria das migrações. Mova seu conteúdo para um CMS que foi construído desde o início para entrega API-first.

CMS Pricing (2026) Melhor Para Content Modeling Tipo de API
Sanity Free tier, $15/user/mo Pro Conteúdo complexo, colaboração real-time Excelente, code-defined GROQ + GraphQL
Contentful Free tier, $300/mo Team Enterprise, grandes times Bom, UI-defined REST + GraphQL
Storyblok Free tier, €106/mo Business Visual editing, componentes Ótimo, visual REST + GraphQL
Strapi v5 Free (self-hosted), Cloud from $29/mo Controle total, open source Flexível, UI-defined REST + GraphQL
Payload CMS 3.0 Free (self-hosted) Desenvolvedores que querem code-first Excelente, code-defined REST + GraphQL

Se seu time está cuidando da migração, normalmente recomendamos Sanity ou Payload — eles dão aos desenvolvedores o máximo controle sobre content modeling enquanto mantêm editores felizes.

Opção 3: Markdown/MDX no Repositório

Para blogs de desenvolvedor e sites de documentação, armazenar conteúdo como arquivos MDX em seu repo Git é a abordagem mais simples. Nenhum CMS para gerenciar, sem chamadas de API, conteúdo versionado junto com código. Mas isso só funciona se seus editores de conteúdo estão confortáveis com workflows Git.

Estratégia de Migração de Conteúdo

Exportando do WordPress

A exportação integrada do WordPress (Tools → Export) oferece um arquivo XML. É um começo, mas é bagunçado. Para migração estruturada, uso um script WP-CLI customizado:

// export-content.php
<?php
$posts = get_posts([
    'post_type' => ['post', 'page', 'your_custom_type'],
    'posts_per_page' => -1,
    'post_status' => 'publish',
]);

$export = [];
foreach ($posts as $post) {
    $export[] = [
        'id' => $post->ID,
        'title' => $post->post_title,
        'slug' => $post->post_name,
        'content' => apply_filters('the_content', $post->post_content),
        'excerpt' => $post->post_excerpt,
        'date' => $post->post_date,
        'modified' => $post->post_modified,
        'author' => get_the_author_meta('display_name', $post->post_author),
        'categories' => wp_get_post_categories($post->ID, ['fields' => 'names']),
        'tags' => wp_get_post_tags($post->ID, ['fields' => 'names']),
        'featured_image' => get_the_post_thumbnail_url($post->ID, 'full'),
        'acf' => function_exists('get_fields') ? get_fields($post->ID) : [],
        'yoast' => [
            'title' => get_post_meta($post->ID, '_yoast_wpseo_title', true),
            'description' => get_post_meta($post->ID, '_yoast_wpseo_metadesc', true),
        ],
    ];
}

file_put_contents('export.json', json_encode($export, JSON_PRETTY_PRINT));

Transformando Conteúdo

Conteúdo do WordPress é armazenado como HTML com markup de bloco Gutenberg. Você precisará decidir: manter o HTML e renderizá-lo, ou converter para o formato estruturado do seu CMS?

Para Sanity, uso @sanity/block-tools para converter HTML para Portable Text. Para Contentful, seu migration CLI trata conversão de rich text. De qualquer forma, aloque tempo para limpeza de conteúdo — conteúdo do WordPress é cheio de [shortcodes], estilos inline, e HTML quebrado que precisa ser limpo.

// migrate-to-sanity.js
import { htmlToBlocks } from '@sanity/block-tools';
import { JSDOM } from 'jsdom';
import { Schema } from '@sanity/schema';

const schema = Schema.compile({ /* your schema */ });
const blockContentType = schema.get('post')
  .fields.find(f => f.name === 'body').type;

function convertPost(wpPost) {
  return {
    _type: 'post',
    title: wpPost.title,
    slug: { current: wpPost.slug },
    publishedAt: wpPost.date,
    body: htmlToBlocks(
      wpPost.content,
      blockContentType,
      { parseHtml: (html) => new JSDOM(html).window.document }
    ),
  };
}

Migração de Imagem

Não pule isso. Baixe cada imagem de wp-content/uploads, re-upload para seu CMS ou CDN (Cloudinary, Vercel Blob Storage, S3), e atualize todas as referências de conteúdo. Tipicamente escrevo um script que:

  1. Rastreia o JSON exportado para URLs de imagem
  2. Baixa cada imagem
  3. Faz upload para o novo storage
  4. Cria um arquivo de mapeamento de URL
  5. Executa find-and-replace em todo conteúdo

Reconstruindo Seu Frontend em Next.js 15

Next.js 15 (estável desde final de 2024, com 15.2 atual em 2026) usa o App Router por padrão. Aqui está a estrutura que uso para sites heavy de conteúdo:

app/
├── layout.tsx          # Root layout com fonts, analytics
├── page.tsx            # Homepage
├── blog/
│   ├── page.tsx        # Blog listing com paginação
│   └── [slug]/
│       └── page.tsx    # Posts de blog individuais
├── [slug]/
│   └── page.tsx        # Páginas genéricas
├── sitemap.ts          # Geração de sitemap dinâmica
├── robots.ts           # robots.txt
└── not-found.tsx       # Custom 404

Geração Estática com ISR

Para a maioria das páginas de conteúdo, Incremental Static Regeneration é o sweet spot — performance estática com frescor dinâmico:

// app/blog/[slug]/page.tsx
import { getPostBySlug, getAllPostSlugs } from '@/lib/cms';
import { notFound } from 'next/navigation';

export async function generateStaticParams() {
  const slugs = await getAllPostSlugs();
  return slugs.map((slug) => ({ slug }));
}

export async function generateMetadata({ params }) {
  const post = await getPostBySlug(params.slug);
  if (!post) return {};
  return {
    title: post.seo?.title || post.title,
    description: post.seo?.description || post.excerpt,
    openGraph: {
      images: [post.featuredImage?.url],
    },
  };
}

export const revalidate = 3600; // Revalidate a cada hora

export default async function BlogPost({ params }) {
  const post = await getPostBySlug(params.slug);
  if (!post) notFound();

  return (
    <article className="prose lg:prose-xl">
      <h1>{post.title}</h1>
      <time dateTime={post.date}>{formatDate(post.date)}</time>
      <PostBody content={post.body} />
    </article>
  );
}

Para sites precisando de atualizações real-time (notícias, conteúdo live), use revalidação on-demand via webhooks do seu CMS. A maioria das plataformas de headless CMS suportam webhook triggers ao publicar conteúdo.

Estrutura de URL e Preservação de SEO

Isso é inegociável. Se você perder sua estrutura de URL, perde seus rankings de search. Período.

Mapa de Redirect

WordPress usa padrões de URL como /2024/03/post-slug/ ou /category/term/. Seu site Next.js provavelmente usa /blog/post-slug. Crie um mapa de redirect:

// next.config.js
module.exports = {
  async redirects() {
    return [
      // URLs baseadas em data para slugs limpos
      {
        source: '/:year(\\d{4})/:month(\\d{2})/:slug',
        destination: '/blog/:slug',
        permanent: true,
      },
      // Arquivos de categoria
      {
        source: '/category/:slug',
        destination: '/blog?category=:slug',
        permanent: true,
      },
      // Paginação
      {
        source: '/page/:num',
        destination: '/blog?page=:num',
        permanent: true,
      },
      // URLs de feed
      {
        source: '/feed',
        destination: '/rss.xml',
        permanent: true,
      },
    ];
  },
};

Para sites grandes (1000+ redirects), use configuração vercel.json do Vercel ou middleware — redirects no next.config.js têm um soft limit de aproximadamente 1024 entradas antes de tempos de build começarem a sofrer.

Dados Estruturados

Plugins do WordPress como Yoast auto-geram JSON-LD. Você precisa replicar isso:

// components/structured-data.tsx
export function ArticleSchema({ post }) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'Article',
    headline: post.title,
    datePublished: post.date,
    dateModified: post.modified,
    author: {
      '@type': 'Person',
      name: post.author,
    },
    image: post.featuredImage?.url,
    publisher: {
      '@type': 'Organization',
      name: 'Your Site Name',
      logo: { '@type': 'ImageObject', url: '/logo.png' },
    },
  };

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
    />
  );
}

Sitemap XML

Next.js 15 torna sitemaps dinâmicos simples:

// app/sitemap.ts
import { getAllPosts, getAllPages } from '@/lib/cms';

export default async function sitemap() {
  const posts = await getAllPosts();
  const pages = await getAllPages();

  return [
    { url: 'https://yoursite.com', lastModified: new Date() },
    ...pages.map((page) => ({
      url: `https://yoursite.com/${page.slug}`,
      lastModified: page.modified,
    })),
    ...posts.map((post) => ({
      url: `https://yoursite.com/blog/${post.slug}`,
      lastModified: post.modified,
    })),
  ];
}

Fazendo Deploy no Vercel: Configuração Que Realmente Funciona

Configuração de Projeto

npx create-next-app@latest my-migrated-site --typescript --tailwind --app
cd my-migrated-site
vercel link

Variáveis de Ambiente

Defina estas no dashboard do Vercel, não em arquivos .env commitados no Git:

CMS_API_URL=https://your-cms-api-endpoint
CMS_API_TOKEN=your-read-only-token
REVALIDATION_SECRET=a-random-string-for-webhook-auth
SITE_URL=https://yoursite.com

Configuração Vercel

// vercel.json
{
  "crons": [
    {
      "path": "/api/revalidate-sitemap",
      "schedule": "0 */6 * * *"
    }
  ],
  "headers": [
    {
      "source": "/fonts/(.*)",
      "headers": [
        { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
      ]
    }
  ]
}

Webhook de Revalidação On-Demand

// app/api/revalidate/route.ts
import { revalidatePath } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
  const secret = request.headers.get('x-revalidation-secret');
  if (secret !== process.env.REVALIDATION_SECRET) {
    return NextResponse.json({ error: 'Invalid secret' }, { status: 401 });
  }

  const body = await request.json();
  const { slug, type } = body;

  if (type === 'post') {
    revalidatePath(`/blog/${slug}`);
    revalidatePath('/blog'); // Revalidate listing também
  } else {
    revalidatePath(`/${slug}`);
  }

  return NextResponse.json({ revalidated: true });
}

Aponte o webhook do seu CMS para https://yoursite.com/api/revalidate com o header secret. Agora atualizações de conteúdo aparecem em segundos sem rebuilds completos.

Benchmarks de Performance: Antes e Depois

Estes são números reais de migrações completadas em 2025-2026:

Métrica WordPress (WP Engine) Next.js (Vercel) Melhoria
Lighthouse Performance 62-78 95-100 +30-40%
Largest Contentful Paint 2.8-4.2s 0.8-1.4s 60-70% mais rápido
Time to First Byte 800ms-1.5s 50-120ms 90%+ mais rápido
Cumulative Layout Shift 0.12-0.25 0.01-0.05 ~80% redução
Custo de hosting mensal $115/mo avg $20-40/mo 60-80% economia
Tempo de build (500 páginas) N/A (dinâmico) 45-90 segundos N/A
Páginas/segundo (ISR) 15-30 req/s 10,000+ from edge Ordens de magnitude

A melhoria de TTFB sozinha vale a migração. WordPress gera cada página através de PHP e MySQL. Vercel serve páginas pré-renderizadas de nós edge em 300+ locais pelo mundo.

Armadilhas Comuns de Migração

Armadilha 1: Esquecer feeds RSS do WordPress. Se pessoas se inscrevem no seu feed, redirecione /feed/ e /rss/ para um novo endpoint RSS. Next.js não gera feeds por padrão — você precisa de uma custom route.

Armadilha 2: Perder shortcodes do WordPress. Conteúdo exportado do WordPress é cheio de [gallery], [embed], e shortcodes específicos de plugin. Se você não parsear e converter estes, renderizam como texto plano. Escreva transformers para cada tipo de shortcode que seu conteúdo usa.

Armadilha 3: Ignorar dados de comentários do WordPress. Se você tem threads de comentários valiosos, migre-os para um serviço como Disqus ou construa um sistema de comentários customizado. A maioria das pessoas só abandonam comentários, mas verifique com stakeholders primeiro.

Armadilha 4: Não testar links internos. Conteúdo do WordPress é cheio de links internos usando URLs absolutas (https://yoursite.com/old-path/). Estes precisam ser atualizados para paths relativos ou sua nova estrutura de URL. Um simples find-and-replace regex durante migração trata a maioria dos casos.

Armadilha 5: Esquecer referências wp-content/uploads. Mesmo após migrar imagens, conteúdo antigo pode referenciar paths /wp-content/uploads/2024/03/image.jpg. Configure um redirect catch-all ou proxy estes para seu novo image CDN.

Se isso parece avassalador, é honestamente normal. Uma migração adequada leva 4-12 semanas dependendo da complexidade do site. Verifique nosso pricing ou entre em contato diretamente se você quer mãos experientes no projeto.

FAQ

Quanto tempo leva uma migração de WordPress para Next.js?

Para um site com 100-500 páginas, espere 4-8 semanas com um desenvolvedor dedicado. Sites maiores com custom post types, e-commerce, ou conteúdo multilíngue podem levar 8-16 semanas. A migração de conteúdo em si é geralmente 20% do trabalho — os outros 80% é reconstruir templates, lidar com edge cases, e testes de QA em cada URL.

Vou perder meus rankings do Google durante a migração?

Não se você tratar os redirects corretamente. Implemente 301 redirects para cada URL que mudar, preserve seus títulos meta e descrições, envie seu novo sitemap para Google Search Console, e use a ferramenta Change of Address se seu domínio mudar. Espere uma flutuação de ranking pequena por 2-4 semanas, depois recuperação ou melhoria conforme o Google reconhece melhores Core Web Vitals.

Posso manter WordPress como meu CMS com Next.js?

Absolutamente. Isso é chamado "headless WordPress" e é uma abordagem popular. Use WPGraphQL para expor seu conteúdo como uma API, depois consuma do Next.js. Seus editores mantêm o admin do WordPress que conhecem. O downside principal é que você ainda mantém uma instalação WordPress — atualizações de segurança, hosting, todo o stack.

Quanto custa migrar de WordPress para Next.js?

DIY com um desenvolvedor: 100-300 horas de trabalho. Migração de agência: tipicamente $15,000-$75,000 dependendo de complexidade. Custos de hosting contínuo geralmente diminuem — Vercel Pro a $20/usuário/mês versus hosting WordPress gerenciado a $50-$300/mês. O ROI vem de custos de hosting reduzidos, melhor performance (que melhora conversion rates), e menor overhead de manutenção.

Devo usar Pages Router ou App Router em Next.js 15?

App Router, completamente. Em 2026, o App Router é o default estável com Server Components, streaming, e parallel routes. O Pages Router ainda funciona e não é deprecado, mas novas features e otimizações são App Router-first. Cada migração que fazemos usa exclusivamente o App Router.

E sobre forms e funcionalidade dinâmica?

API routes do Next.js (ou Server Actions no App Router) tratam form submissions, search, autenticação, e qualquer lógica server-side. Para contact forms, você pode usar Server Actions com um serviço como Resend para entrega de email. Para search, considere Algolia ou Meilisearch. Para autenticação, NextAuth.js (agora Auth.js v5) cobre a maioria dos casos.

Vercel é a única opção para hosting Next.js?

Não. Você pode fazer deploy de Next.js em Netlify, AWS Amplify, Cloudflare Pages, ou auto-hospedar com Node.js. Entretanto, Vercel é construída pelo time Next.js, e a integração se mostra — ISR, edge middleware, image optimization, e analytics todos funcionam melhor em Vercel. O gap de DX entre Vercel e alternativas estreitou em 2026, mas Vercel permanece o caminho de menor resistência.

E se eu precisar migrar uma loja WooCommerce?

Este é um projeto maior. A maioria dos times migram o storefront para Next.js enquanto movem o backend de comércio para Shopify (usando Storefront API), Medusa.js, ou Saleor. O framework Hydrogen do Shopify é outra opção, mas se você quer controle total sobre o frontend, Next.js com API do Shopify é o caminho mais provado. Espere que a migração de e-commerce adicione 4-8 semanas à sua timeline.