Migration WordPress vers Next.js : SaaS Financier Économise 420K ARR
Migration WordPress vers Next.js : Comment une SaaS financière a économisé 420K$/an
En fin 2024, une SaaS de services financiers de Series C nous a contactés avec un problème qui leur coûtait réellement de l'argent. Leur site marketing, portail client et hub de documentation tournaient tous sur WordPress avec un fouillis de plugins premium, une pile de licences CMS d'entreprise à 420K$/an, et des temps de chargement qui mettaient mal à l'aise son équipe de conformité. Ils avaient besoin de passer à une architecture headless moderne sans une seule seconde de downtime — parce que dans les services financiers, le downtime signifie un contrôle réglementaire, une perte de confiance, et des appels téléphoniques très désagréables de personnes très sérieuses.
Voici l'histoire complète de comment nous avons réussi le coup.
Table des matières
- Le point de départ : Un monolithe WordPress sous pression
- Pourquoi Next.js headless était le bon choix
- L'architecture de migration
- Stratégie zéro downtime : L'exécution en parallèle
- Résultats de performance : 3x plus rapide et bien au-delà
- Détail des économies de 420K$ en licences
- Plongée technique : Détails clés de l'implémentation
- Leçons apprises à la dure
- Chronologie et structure d'équipe
- FAQ

Le point de départ : Un monolithe WordPress sous pression
Laissez-moi peindre le tableau. Cette entreprise — nous l'appellerons FinEdge (NDA, vous comprenez) — avait approximativement 12 000 pages de contenu réparties sur trois propriétés web distinctes :
- Site marketing — Pages produits, landing pages, blog avec plus de 2 400 articles
- Portail client — Tableaux de bord de compte, flux d'intégration, gestion documentaire
- Hub de documentation — Docs API, guides de conformité, tutoriels d'intégration
Les trois fonctionnaient sur une installation WordPress multisite unique hébergée sur le tier entreprise de WP Engine. La situation des plugins était... quelque chose. Ils exécutaient 47 plugins actifs, incluant WPGraphQL, Advanced Custom Fields Pro, Yoast SEO Premium, WP Rocket, Gravity Forms, et un plugin personnalisé que leur ancienne agence avait créé pour gérer la journalisation de conformité SOC 2 des changements de contenu.
Les véritables points de friction :
- Temps de chargement moyen de 4,2 secondes sur mobile (données Google CrUX)
- Core Web Vitals échouant sur 68% des pages — LCP était brutal à 5,1s médiane
- 420K$/an en licences couvrant l'hébergement WP Engine entreprise, les plugins premium, un WAF, CDN, et un environnement de staging séparé
- Éditeurs de contenu attendant 8-12 secondes pour que WordPress admin réponde pendant les heures de pointe
- Correctifs de sécurité nécessitant du temps DevOps dédié toutes les deux semaines — les régulateurs de services financiers ne plaisantent pas
- Pas d'aperçus de déploiement — l'équipe de contenu devait pousser vers le staging et attendre 4 minutes pour l'invalidation du cache
Leur VP d'Engineering nous a dit lors de l'appel de découverte : « Nous dépensons plus pour notre infrastructure de site web que pour deux ingénieurs séniors. Et c'est toujours lent. »
Pourquoi Next.js headless était le bon choix
Nous avons évalué plusieurs options pendant la phase d'architecture. Voici ce qui était sur la table :
| Option | Avantages | Inconvénients | Coût annuel estimé |
|---|---|---|---|
| WordPress (optimisé) | Familier à l'équipe, pas de migration nécessaire | Toujours lent, licences inchangées | 420K$ |
| Webflow Enterprise | Édition visuelle, déploiement rapide | Limité pour les besoins de portail/app, vendor lock-in | 180K$ |
| Next.js + Sanity | Extrêmement rapide, flexible, aperçu en temps réel | Effort de migration, ramp-up d'équipe | 38K$ |
| Next.js + Contentful | Fortes fonctionnalités entreprise, bon DX | Tarification par utilisateur qui scale mal | 95K$ |
| Astro + Storyblok | Excellent pour contenu statique, léger | Moins mature pour les besoins de portail dynamique | 42K$ |
Nous avons choisi Next.js 14 (App Router) avec Sanity comme CMS headless. Voici pourquoi :
- Le portail de FinEdge avait des routes dynamiques et authentifiées qui nécessitaient un rendu côté serveur. Next.js le gère nativement avec les React Server Components.
- La collaboration en temps réel de Sanity et le langage de requête GROQ donnaient aux éditeurs de contenu une expérience dramatiquement meilleure que WordPress.
- Le modèle de tarification (plan Growth de Sanity à 99$/mois + Vercel Pro) signifiait que les coûts d'infrastructure chutaient de 420K$ à approximativement 38K$ annuels.
- L'équipe d'engineering de FinEdge connaissait déjà React. Le ramp-up sur Next.js s'est mesuré en jours, pas en mois.
Nous avons sérieusement envisagé Astro pour le hub de documentation puisqu'il s'agit principalement de contenu statique, mais la simplicité opérationnelle de garder tout dans un seul framework l'a emporté. Si le site de docs avait été un projet autonome, Astro aurait été le choix.
L'architecture de migration
Voici l'architecture haut niveau que nous avons conçue :
┌─────────────────┐ ┌──────────────────┐
│ Sanity CMS │────▶│ Next.js on │
│ (Contenu) │ │ Vercel (Edge) │
└─────────────────┘ └──────────────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ Cloudflare │
│ │ (DNS + WAF) │
│ └──────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Pipeline Media │ │ Utilisateurs │
│ (Cloudinary) │ │ finaux │
└─────────────────┘ └──────────────────┘
Les composants clés :
Couche de contenu
- Sanity comme CMS primaire pour le contenu marketing, articles de blog et documentation
- Schémas Sanity personnalisés mappés à leurs types de contenu WordPress existants
- Portable Text pour le contenu riche (remplaçant les blocs Gutenberg de WordPress)
Couche application
- Next.js 14 avec App Router, déployé sur le plan Pro de Vercel
- React Server Components pour le site marketing et la documentation
- Composants client uniquement là où l'interactivité était véritablement nécessaire (formulaires, tableaux de bord, graphiques interactifs)
- Middleware pour l'authentification sur les routes du portail, intégrée avec leur setup Auth0 existant
Couche infrastructure
- Vercel pour l'hébergement et les edge functions
- Cloudflare pour la gestion DNS et les règles WAF supplémentaires (exigence de conformité des services financiers)
- Cloudinary pour l'optimisation et la transformation d'images — remplaçant 3 plugins d'images WordPress

Stratégie zéro downtime : L'exécution en parallèle
C'était la partie qui m'empêchait de dormir. FinEdge ne pouvait pas se permettre même quelques minutes de downtime. Leur portail client traite des transactions financières, et toute interruption déclenche des rapports d'incident obligatoires auprès des régulateurs.
Voici comment nous avons fait :
Phase 1 : Synchronisation du contenu (Semaines 1-3)
Nous avons construit un pipeline de synchronisation WordPress-vers-Sanity personnalisé qui a fonctionné continuellement pendant la période de migration :
// Version simplifiée de notre worker de synchronisation WP-vers-Sanity
import { createClient } from '@sanity/client'
import WPGraphQL from './wp-graphql-client'
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID,
dataset: 'production',
token: process.env.SANITY_WRITE_TOKEN,
apiVersion: '2024-10-01',
useCdn: false,
})
async function syncPosts(since: string) {
const posts = await WPGraphQL.getModifiedPosts(since)
const transaction = sanity.transaction()
for (const post of posts) {
const sanityDoc = transformWPToSanity(post)
transaction.createOrReplace(sanityDoc)
}
await transaction.commit()
console.log(`Synced ${posts.length} posts`)
}
// Executed every 5 minutes via cron
Cela signifiait que les éditeurs de contenu pouvaient continuer à travailler dans WordPress pendant toute la migration. Chaque changement qu'ils faisaient était automatiquement synchronisé vers Sanity en moins de 5 minutes.
Phase 2 : Déploiement parallèle (Semaines 4-8)
Nous avons déployé le site Next.js sur un sous-domaine (next.finedge.com) et avons exécuté les deux sites simultanément. Notre processus QA comparait chaque page :
- Tests de régression visuelle avec Playwright sur plus de 200 pages critiques
- Vérifications de parité SEO (balises meta, données structurées, URLs canoniques, sitemaps)
- Benchmarks de performance sur chaque template de page
- Audits d'accessibilité (WCAG 2.1 AA — obligatoire pour les services financiers)
Phase 3 : La transition (Semaine 9)
Le vrai changement était anticlimatique — ce qui est exactement ce qu'on veut. Nous avons utilisé l'équilibrage de charge de Cloudflare pour décaler le trafic progressivement :
- Heure 0: 5% du trafic vers Next.js, 95% vers WordPress
- Heure 2: 25% / 75% (surveillance des taux d'erreur, Core Web Vitals)
- Heure 6: 50% / 50%
- Heure 12: 90% / 10%
- Heure 24: 100% Next.js, WordPress en mode lecture seule
- Semaine 2: WordPress désactivé
Zéro erreur. Zéro downtime. Les tableaux de bord de monitoring étaient ennuyeusement verts.
Résultats de performance : 3x plus rapide et bien au-delà
Voici les vrais chiffres, mesurés 30 jours après la migration en utilisant les données Google CrUX et Vercel Analytics :
| Métrique | WordPress (Avant) | Next.js (Après) | Amélioration |
|---|---|---|---|
| LCP (p75) | 5,1s | 1,2s | 4,25x plus rapide |
| FID / INP (p75) | 280ms | 68ms | 4,1x plus rapide |
| CLS (p75) | 0,18 | 0,02 | 9x mieux |
| TTFB (p75) | 1,8s | 0,12s | 15x plus rapide |
| Lighthouse Performance | 34 | 96 | +62 points |
| Pages passant CWV | 32% | 98% | +66% |
| Time to Interactive | 6,8s | 1,4s | 4,9x plus rapide |
Le titre « 3x plus rapide » en fait réellement moins que la réalité. Sur la plupart des métriques, nous avons vu des améliorations de 4-5x. TTFB était la star — passant de 1,8 secondes à 120 millisecondes grâce au réseau Edge de Vercel et à l'ISR (Incremental Static Regeneration).
Le trafic organique a augmenté de 31% dans les 90 premiers jours post-migration. Leur équipe SEO a attribué cela principalement aux améliorations des Core Web Vitals et aux vitesses de crawling plus rapides de Googlebot.
Détail des économies de 420K$ en licences
Parlons argent. Voici exactement où allaient les 420K$ et ce qui l'a remplacé :
| Poste | Coût annuel WordPress | Coût annuel Next.js | Économies |
|---|---|---|---|
| Hébergement WP Engine Enterprise | 150 000$ | — | 150 000$ |
| Vercel Pro (Team plan) | — | 2 400$ | — |
| Licences de plugins premium (47 plugins) | 28 000$ | — | 28 000$ |
| Plan Growth Sanity | — | 1 188$ | — |
| Cloudinary Pro | — | 2 388$ | — |
| WAF Entreprise (Sucuri) | 36 000$ | — | 36 000$ |
| Cloudflare Pro | — | 2 400$ | — |
| Contrat de maintenance WordPress personnalisé | 96 000$ | — | 96 000$ |
| CDN (séparé de WP Engine) | 24 000$ | — | 24 000$ |
| Hébergement d'environnement de staging | 18 000$ | — | 18 000$ |
| Audits de sécurité WordPress (trimestriels) | 48 000$ | — | 48 000$ |
| Temps de l'équipe DevOps (FTE partielle) | 120 000$ | 30 000$ | 90 000$ |
| Totaux | 520 000$ | 38 376$ | 481 624$ |
Les économies réelles se sont avérées être plus proches de 482K$, pas 420K$. L'estimation originale de 420K$ de la phase de découverte était conservatrice — nous n'avions pas initialement compté la réduction du temps DevOps ou l'élimination des audits de sécurité trimestriels (Vercel et Cloudflare gèrent la plupart de ce que ces audits couvraient).
Le calcul du ROI est simple. Notre projet de migration a coûté à FinEdge environ 185K$ en honoraires d'agence sur l'engagement de 10 semaines. Cet investissement s'est amorti en moins de 5 mois.
Plongée technique : Détails clés de l'implémentation
Gérer 2 400 articles de blog avec l'ISR
Nous n'avons pas généré statiquement tous les 2 400 articles de blog au moment du build. Cela aurait rendu les déploiements douloureusement lents. À la place, nous avons utilisé l'ISR avec revalidation à la demande :
// app/blog/[slug]/page.tsx
import { sanityFetch } from '@/lib/sanity'
import { postQuery } from '@/lib/queries'
export const revalidate = 3600 // Revalidate every hour as fallback
export async function generateStaticParams() {
// Pré-générer uniquement les 100 meilleurs articles par trafic
const topPosts = await sanityFetch({
query: `*[_type == "post"] | order(pageViews desc) [0...100] { "slug": slug.current }`
})
return topPosts.map((post) => ({ slug: post.slug }))
}
export default async function BlogPost({ params }) {
const post = await sanityFetch({
query: postQuery,
params: { slug: params.slug },
tags: [`post:${params.slug}`]
})
// ... render post
}
Quand les éditeurs de contenu publient ou mettent à jour dans Sanity, un webhook frappe notre endpoint de revalidation :
// app/api/revalidate/route.ts
import { revalidateTag } from 'next/cache'
import { NextRequest } from 'next/server'
export async function POST(req: NextRequest) {
const body = await req.json()
const secret = req.headers.get('x-sanity-webhook-secret')
if (secret !== process.env.SANITY_WEBHOOK_SECRET) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
// Revalidate specific content
if (body._type === 'post') {
revalidateTag(`post:${body.slug.current}`)
revalidateTag('posts-list')
}
return Response.json({ revalidated: true })
}
Les mises à jour de contenu apparaissent maintenant sur le site en direct en moins de 3 secondes. Comparez cela aux 4 minutes d'invalidation de cache qu'ils avaient avec WordPress + WP Rocket.
Authentification pour le portail client
Les routes du portail avaient besoin d'une authentification côté serveur. Nous avons utilisé le middleware Next.js combiné avec leur setup Auth0 existant :
// middleware.ts
import { NextResponse } from 'next/server'
import { getSession } from '@auth0/nextjs-auth0/edge'
export async function middleware(req) {
if (req.nextUrl.pathname.startsWith('/portal')) {
const session = await getSession(req, NextResponse.next())
if (!session?.user) {
return NextResponse.redirect(new URL('/api/auth/login', req.url))
}
}
return NextResponse.next()
}
export const config = {
matcher: ['/portal/:path*']
}
Cela s'exécute à la limite, donc les requêtes non authentifiées sont redirigées avant même qu'elles ne frappent le serveur d'applications. Rapide et sécurisé.
Carte de redirection 301
Nous avions approximativement 340 URLs qui ont changé de structure pendant la migration. Un site de services financiers ne peut absolument pas avoir de liens cassés — chaque lien entrant des documents réglementaires, des sites partenaires, et du contenu historique doit se résoudre correctement.
Nous avons construit une carte de redirection dans next.config.js et l'avons complétée avec une recherche de redirection dynamique depuis Sanity pour les redirections gérées par l'éditeur :
// next.config.js (partiel)
module.exports = {
async redirects() {
return [
// Redirections statiques pour les changements d'URL connus
...require('./redirects.json').map(r => ({
source: r.from,
destination: r.to,
permanent: true,
})),
]
},
}
Six mois après le lancement, Google Search Console affiche zéro erreurs 404 de la migration. Chaque redirection fonctionne.
Leçons apprises à la dure
1. Les blocs Gutenberg de WordPress font mal à convertir
Nous avons sous-estimé l'effort pour convertir les blocs Gutenberg au Portable Text de Sanity. FinEdge avait utilisé 23 types de blocs différents, incluant des blocs personnalisés que leur ancienne agence avait créés. Budgétez au moins 20% de temps supplémentaire que ce que vous pensez pour la transformation de contenu.
2. La formation des éditeurs de contenu n'est pas optionnelle
Le Studio Sanity est intuitif, mais ce n'est pas WordPress. Nous avons exécuté trois sessions de formation de 90 minutes et créé un Studio Sanity personnalisé avec des workflows guidés. L'équipe de contenu est passée du sceptique à l'enthousiaste en deux semaines, mais cet investissement en formation était critique.
3. La conformité des services financiers ajoute de la complexité
Chaque déploiement avait besoin d'une piste d'audit. Chaque changement de contenu avait besoin d'être enregistré avec des timestamps et l'attribution de l'utilisateur. Nous avons construit un plugin Sanity personnalisé qui enregistre toutes les mutations de document dans une table d'audit ajout-seul dans leur base de données PostgreSQL existante. Cela a pris une semaine supplémentaire qui n'était pas dans la portée originale.
4. N'oubliez pas les formulaires
Gravity Forms géraient 14 types de formulaires différents sur le site WordPress. Nous les avons remplacés par React Hook Form + validation Zod sur le frontend et server actions sur le backend, avec les soumissions allant vers leur CRM HubSpot existant. Cette migration seule a pris une semaine complète.
Chronologie et structure d'équipe
Durée totale du projet : 10 semaines
| Semaine | Focus | Équipe |
|---|---|---|
| 1 | Architecture, conception de schéma Sanity, audit de contenu | 2 devs, 1 architect |
| 2-3 | Pipeline de synchronisation du contenu, personnalisation du Studio Sanity | 2 devs, 1 stratège contenu |
| 4-5 | Construction du site marketing (Next.js) | 3 devs |
| 6-7 | Migration du portail, authentification, formulaires | 3 devs |
| 8 | Hub de documentation, audit SEO, carte de redirection | 2 devs, 1 spécialiste SEO |
| 9 | QA, régression visuelle, tests de performance | 2 devs, 1 QA |
| 10 | Transition progressive du trafic, monitoring, désactivation de WordPress | 2 devs, 1 DevOps |
La taille maximale de l'équipe était de 4 personnes. La plupart du projet s'est déroulé avec 2-3 développeurs. Ce n'est pas un engagement de 15 personnes sur 6 mois — c'est une équipe focalisée et expérimentée exécutant une migration bien planifiée.
Si vous envisagez une migration similaire pour votre organisation, nous avons documenté notre approche de développement de CMS headless et notre structure tarifaire est transparente. Nous sommes aussi heureux de discuter sur un appel pour parler de votre situation spécifique — contactez-nous ici.
FAQ
Combien de temps prend généralement une migration WordPress vers Next.js ? Pour un site de cette complexité (12 000 pages, portail client, hub de documentation), 10 semaines est réaliste avec une équipe expérimentée. Les sites marketing plus simples avec 100-500 pages peuvent être migrés en 4-6 semaines. La plus grande variable est la complexité du contenu — combien de types de posts personnalisés, de types de blocs, et de fonctionnalités dépendantes de plugins vous exécutez.
Pouvez-vous migrer WordPress vers Next.js sans aucun downtime ? Oui, mais cela nécessite de la planification. La clé est d'exécuter les deux systèmes en parallèle avec un pipeline de synchronisation du contenu, puis d'utiliser le changement de trafic au niveau DNS pour décaler progressivement les utilisateurs vers le nouveau site. Nous avons fait cela avec succès pour plusieurs clients. L'exigence critique est que votre contenu reste synchronisé entre les deux systèmes pendant la période de transition.
Combien coûte une migration WordPress vers un CMS headless ? Cela dépend fortement de la portée. Une migration de site marketing simple pourrait coûter 30K$-60K$. Une migration d'entreprise comme celle de FinEdge — avec un portail client, des exigences de conformité, et 12 000 pages — était de 185K$. Le calcul du ROI importe plus que le coût absolu. L'investissement de FinEdge s'est amorti en moins de 5 mois uniquement grâce aux économies de licences.
Next.js est-il réellement plus rapide que WordPress ? Dans pratiquement tous les cas, oui — significativement plus rapide. WordPress génère HTML à chaque requête (à moins d'être lourdement cachée), et même avec des plugins de cache comme WP Rocket, vous êtes limité par le temps de réponse PHP et le poids de l'écosystème WordPress. Next.js avec ISR ou génération statique sert des pages pré-construites depuis la limite. Nous voyons généralement des améliorations de 3-5x dans les Core Web Vitals.
Quel CMS headless devrais-je utiliser avec Next.js ? Cela dépend de votre équipe et de vos exigences. Sanity excelle pour la modélisation de contenu personnalisée et la collaboration en temps réel. Contentful est fort pour les équipes d'entreprise qui veulent une approche plus structurée et opinionée mais devient cher par siège. Storyblok est excellent si l'édition visuelle est une priorité. Pour les sites plus simples, même des fichiers Markdown dans un repo Git peuvent fonctionner. Nous évaluons cela au cas par cas — il n'y a pas de réponse universelle.
Perdez-vous du SEO lors de la migration de WordPress vers Next.js ? Pas si vous le faites correctement. Les trois choses qui importent : mappage complet des redirections 301 afin que aucune URL existante ne retourne 404, préservation de toutes les balises meta et données structurées, et soumission des sitemaps mis à jour à Google Search Console immédiatement après la transition. FinEdge a vu une augmentation de 31% du trafic organique dans les 90 jours, largement impulsée par les améliorations des Core Web Vitals.
Que se passe-t-il pour les plugins WordPress après la migration ? La fonctionnalité de chaque plugin doit être répliquée ou remplacée. Certains sont simples — les plugins SEO sont remplacés par des métadonnées dans vos composants Next.js, les plugins de cache deviennent inutiles, et les plugins de formulaire sont remplacés par des bibliothèques de formulaires React. D'autres, comme les plugins de journalisation de conformité personnalisée, ont besoin de code de remplacement sur mesure. C'est pourquoi un audit exhaustif des plugins pendant la découverte est essentiel.
Les éditeurs de contenu peuvent-ils encore utiliser un éditeur visuel après le passage à headless ? Oui. Sanity Studio fournit une interface d'édition personnalisable avec aperçu en temps réel. C'est différent de l'éditeur de blocs de WordPress, mais la plupart des équipes de contenu le préfèrent après la courbe d'apprentissage initiale. L'outil Presentation de Sanity offre maintenant une véritable édition visuelle avec fonctionnalité click-to-edit sur l'aperçu en direct. Nous avons aussi configuré les déploiements d'aperçu sur Vercel pour que les éditeurs voient exactement comment leur contenu apparaîtra avant la publication.