Vous avez dépassé Strapi CMS : Construire avec Payload + Supabase
Quand vous avez dépassé Strapi CMS : Construire avec Payload + Supabase
J'ai mis en place Strapi pour au moins une douzaine de projets clients au cours des dernières années. C'est un excellent CMS pour démarrer -- panneau d'administration convivial, écosystème de plugins décent, documentation solide. Mais environ 18 mois plus tard, presque toutes les équipes avec lesquelles j'ai travaillé se heurtent à un mur. Les migrations deviennent douloureuses, les personnalisations semblent hacky, et vos développeurs frontend adorant TypeScript commencent à se plaindre de l'expérience développeur. Si cela vous semble familier, vous n'êtes pas seul. Laissez-moi vous montrer les signes que vous avez dépassé Strapi, et plus important encore, ce qu'il faut construire à la place.

Table des matières
- La lune de miel : Pourquoi Strapi fonctionne bien au départ
- Six signes que vous avez dépassé Strapi
- Comprendre vos options : Payload vs Supabase vs rester
- Pourquoi Payload CMS est l'étape naturelle suivante
- Où Supabase s'inscrit (et où ce n'est pas le cas)
- La pile Payload + Supabase : Plongée en profondeur dans l'architecture
- Stratégie de migration : Quitter Strapi sans perdre la tête
- Benchmarks de performance et chiffres du monde réel
- Quand cette pile n'est pas le bon choix
- FAQ
La lune de miel : Pourquoi Strapi fonctionne bien au départ
Soyons honnêtes. Strapi a 65K+ étoiles GitHub pour une bonne raison. Quand vous lancez un nouveau projet axé sur le contenu, le Content-Type Builder est véritablement utile. Vous cliquez dans une GUI, définissez quelques champs, et boom -- vous avez des APIs REST et GraphQL. Les éditeurs de contenu non techniques peuvent se connecter au panneau d'administration et commencer à publier en une heure.
Pour les startups en phase initiale, les sites marketing et les blogs, Strapi est un choix parfaitement raisonnable. Il supporte PostgreSQL, MySQL, MariaDB et SQLite. La place de marché des plugins dispose de plus de 100 extensions communautaires. Et l'édition communautaire est gratuite sous la licence MIT.
J'ai recommandé Strapi de nombreuses fois. Je ne suis pas ici pour le critiquer. Je suis ici pour parler de ce qui se passe ensuite.
Six signes que vous avez dépassé Strapi
Ce sont les schémas que je vois régulièrement. Si trois ou plus de ces points résonnent, il est temps de commencer à planifier votre migration.
1. Les migrations vous rendent nerveux
La mise à niveau de la v4 à la v5 est celle qui a cassé beaucoup d'équipes. Strapi a documenté 50+ changements cassants. En pratique, j'ai vu des migrations prendre 40+ heures de temps développeur pour des projets de complexité moyenne. Ce n'est pas un bump de version mineure -- c'est une réécriture de votre couche de contenu.
Si vous redoutez la prochaine version majeure parce que vous savez qu'elle cassera la moitié de vos contrôleurs personnalisés, vous avez dépassé l'outil.
2. Vos développeurs se battent contre le framework
Le Content-Type Builder de Strapi est excellent pour les utilisateurs non techniques. Pour les développeurs qui vivent en TypeScript et veulent des schémas code-first, c'est un goulot d'étranglement. La GUI génère des fichiers que vous n'êtes pas censé éditer. Les hooks de cycle de vie semblent boulonnés. Le support TypeScript a été ajouté tard dans la v4 et ce n'est toujours pas natif -- c'est plus une réflexion a posteriori.
Quand votre équipe commence à construire des contournements pour le framework au lieu de construire des fonctionnalités avec lui, c'est un signal clair.
3. La performance devient un problème
Les démarrages à froid de Strapi se situent généralement entre 500ms et 2000ms. La latence mondiale se situe entre 200-500ms sans mise en cache agressif. Pour un blog, c'est bien. Pour une plateforme de commerce électronique servant des utilisateurs dans plusieurs régions, ce n'est pas le cas.
J'avais un client exécutant un catalogue de produits multilingue sur Strapi. Une fois qu'ils ont dépassé ~50 000 entrées de contenu avec des relations profondes, les temps de réponse de l'API ont grimpé au-delà de la marque des 2 secondes. Aucune quantité d'indexation n'a résolu le problème.
4. Vous avez besoin de fonctionnalités verrouillées derrière des niveaux payants
Le plan Growth de Strapi coûte 45 $/mois et inclut 3 sièges (sièges supplémentaires à 15 $/siège). Cela déverrouille les fonctionnalités d'IA, l'aperçu en direct et l'historique du contenu. La tarification Enterprise est personnalisée.
Le problème n'est pas le prix -- c'est le principe. Des fonctionnalités comme l'aperçu en direct et le versioning du contenu semblent essentielles pour un CMS en 2025. Les avoir bloquées derrière un abonnement sur un outil open-source énerve les équipes de développeurs.
5. Votre pile a évolué au-delà de l'architecture de Strapi
Si vous êtes allé jusqu'au bout avec Next.js, Vercel et TypeScript, Strapi commence à ressembler à un appendice maladroit. Il s'exécute comme un service Node.js séparé. Cela signifie des déploiements séparés, une surveillance séparée, des préoccupations de mise à l'échelle séparées. Votre équipe frontend se déploie sur Vercel en secondes tandis que votre CMS a besoin de sa propre infrastructure.
6. Les extensions personnalisées ressemblent à une chirurgie
Vous voulez ajouter une logique de champ conditionnel ? Des blocs répétables imbriqués avec validation ? Des composants de panneau d'administration personnalisés ? Dans Strapi, chacun de ces éléments est possible mais douloureux. Le panneau d'administration est une application React, mais l'étendre signifie naviguer dans un système d'extension propriétaire qui ne ressemble pas au développement React normal.

Comprendre vos options : Payload vs Supabase vs rester
Avant d'aller plus loin, soyons clairs sur ce que ces outils sont réellement, car je les vois conflés constamment.
| Outil | Ce que c'est réellement | Idéal pour | Pas idéal pour |
|---|---|---|---|
| Strapi | CMS headless open-source avec GUI d'administration | Éditeurs de contenu, génération rapide d'API | Équipes code-first, applications haute performance |
| Payload CMS | Framework CMS code-first qui s'exécute dans Next.js | Développeurs TypeScript, applications de contenu personnalisées | Opérateurs solo non techniques |
| Supabase | Plateforme backend open-source (BD, auth, stockage, temps réel) | Données d'application, authentification, stockage de fichiers | Flux de travail d'édition de contenu |
| Directus | CMS headless SQL-first avec APIs auto-générées | Équipes avec bases de données existantes | Intégration profonde Next.js |
| Sanity | CMS headless géré avec collaboration en temps réel | Équipes éditoriales, contenu structuré | Auto-hébergement économique |
Payload et Supabase ne sont pas des concurrents -- ils sont complémentaires. Payload gère votre modélisation de contenu, votre interface utilisateur d'administration et vos APIs de contenu. Supabase gère l'hébergement de votre base de données, l'authentification, le stockage de fichiers et les abonnements en temps réel. Ensemble, ils remplacent Strapi et bien plus.
Pourquoi Payload CMS est l'étape naturelle suivante
Payload fait beaucoup de vagues à travers 2025 et dans 2026. MG Software l'a qualifié de « perturbateur de marché » pour l'intégration TypeScript/Next.js, et je pense que c'est juste.
Voici la différence architecturale fondamentale : Payload s'exécute à l'intérieur de votre application Next.js. Pas à côté. Pas comme un service séparé. À l'intérieur. Votre CMS et votre frontend partagent le même déploiement, les mêmes types TypeScript, le même processus de construction.
Définition de schéma Code-First
Au lieu de cliquer dans une GUI pour créer des types de contenu, vous écrivez du TypeScript :
import { CollectionConfig } from 'payload';
export const Products: CollectionConfig = {
slug: 'products',
admin: {
useAsTitle: 'name',
defaultColumns: ['name', 'price', 'status'],
},
access: {
read: () => true,
create: ({ req: { user } }) => user?.role === 'admin',
},
fields: [
{
name: 'name',
type: 'text',
required: true,
},
{
name: 'price',
type: 'number',
min: 0,
},
{
name: 'description',
type: 'richText',
},
{
name: 'category',
type: 'relationship',
relationTo: 'categories',
hasMany: false,
},
{
name: 'variants',
type: 'array',
fields: [
{ name: 'sku', type: 'text', required: true },
{ name: 'color', type: 'select', options: ['red', 'blue', 'green'] },
{
name: 'stock',
type: 'number',
admin: {
condition: (data, siblingData) => siblingData?.sku !== undefined,
},
},
],
},
],
hooks: {
afterChange: [
async ({ doc, operation }) => {
if (operation === 'update' && doc.stock === 0) {
// Trigger restock notification
}
},
],
},
};
C'est un type de contenu réel avec logique de champ conditionnel, tableaux imbriqués, champs de relation, contrôle d'accès basé sur les rôles et hooks de cycle de vie. Tout dans un fichier. Tout type-safe. Tout versionné dans Git.
Essayez de faire cela dans Strapi sans toucher trois fichiers différents et le système d'extension d'administration.
Trois couches d'API
Payload génère automatiquement des APIs REST et GraphQL à partir de votre schéma. Mais la fonctionnalité remarquable est l'API locale -- les requêtes de base de données directes à partir de votre code côté serveur sans surcharge HTTP :
// À l'intérieur d'un composant serveur Next.js
import { getPayload } from 'payload';
import config from '@payload-config';
export default async function ProductPage({ params }) {
const payload = await getPayload({ config });
const product = await payload.findByID({
collection: 'products',
id: params.id,
depth: 2, // Populate relationships 2 levels deep
});
return <ProductDetail product={product} />;
}
Pas d'appels fetch. Pas de routes API. Pas de surcharge de sérialisation. C'est pourquoi Payload se compare à environ 7x plus rapide que Strapi pour la récupération de contenu dans des configurations comparables.
Où Supabase s'inscrit (et où ce n'est pas le cas)
Supabase n'est pas un CMS. Je veux être vraiment clair à ce sujet. C'est une plateforme backend construite sur PostgreSQL. Mais il résout plusieurs problèmes que Strapi gère mal et que Payload ne gère pas du tout.
Ce que Supabase apporte à la pile
- PostgreSQL géré : L'adaptateur PostgreSQL de Payload se connecte directement à une base de données Supabase. Vous obtenez le pooling de connexion, les sauvegardes automatiques et un tableau de bord pour les requêtes SQL directes. Le plan Pro commence à 25 $/mois et s'adapte à l'utilisation.
- Authentification : Supabase Auth supporte email/mot de passe, liens magiques, fournisseurs OAuth et la sécurité au niveau des lignes. Si votre application a des fonctionnalités destinées aux utilisateurs au-delà de l'administration du CMS, c'est énorme.
- Stockage de fichiers : Stockage d'objets compatible S3 avec CDN. Payload peut gérer les téléchargements de médias, mais Supabase Storage gère les fichiers d'application, les téléchargements d'utilisateurs et tout ce qui sort du contexte du CMS.
- Abonnements en temps réel : LISTEN/NOTIFY de PostgreSQL enveloppé dans une API WebSocket propre. Associez cela à l'aperçu en direct de Payload pour des expériences d'édition de contenu en temps réel.
- Edge Functions : Fonctions serverless basées sur Deno pour les gestionnaires webhook, les travaux de fond et les intégrations.
Ce que Supabase ne fait pas
Il ne vous donne pas un panneau d'administration pour les éditeurs de contenu. Il ne génère pas d'APIs de contenu avec des champs de texte enrichi et la gestion des médias. Il ne gère pas la localisation du contenu ou l'historique des versions. C'est le travail de Payload.
La pile Payload + Supabase : Plongée en profondeur dans l'architecture
Voici comment je configure cela pour les équipes migrant depuis Strapi. C'est l'architecture que nous recommandons généralement à Social Animal pour les projets de développement Next.js où la gestion de contenu est une exigence principale.
Structure du projet
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (frontend)/ # Pages publiques
│ │ └── (payload)/ # Routes d'administration du CMS (auto-générées)
│ ├── collections/ # Configurations de collection Payload
│ │ ├── Posts.ts
│ │ ├── Products.ts
│ │ └── Users.ts
│ ├── globals/ # Configurations globales Payload
│ │ └── SiteSettings.ts
│ ├── lib/
│ │ └── supabase.ts # Initialisation du client Supabase
│ └── payload.config.ts # Configuration principale Payload
├── supabase/
│ └── migrations/ # Migrations BD Supabase
├── .env.local
└── package.json
Connexion de Payload à PostgreSQL Supabase
// payload.config.ts
import { buildConfig } from 'payload';
import { postgresAdapter } from '@payloadcms/db-postgres';
import { lexicalEditor } from '@payloadcms/richtext-lexical';
import { Posts } from './collections/Posts';
import { Products } from './collections/Products';
export default buildConfig({
db: postgresAdapter({
pool: {
connectionString: process.env.SUPABASE_DB_URL,
// Utilisez le connection pooler de Supabase pour serverless
max: 10,
},
}),
editor: lexicalEditor(),
collections: [Posts, Products],
secret: process.env.PAYLOAD_SECRET,
typescript: {
outputFile: path.resolve(__dirname, 'payload-types.ts'),
},
});
Une note importante : utilisez l'URL du connection pooler Supabase (port 6543), pas l'URL de connexion directe, lors du déploiement dans des environnements serverless comme Vercel. Les connexions directes fonctionnent bien pour le développement local.
Ajout de l'authentification Supabase pour les utilisateurs d'application
Payload gère l'authentification d'administration du CMS. Supabase gère tout le reste :
// lib/supabase.ts
import { createClient } from '@supabase/supabase-js';
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
// Dans un composant serveur ou une route API
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';
export async function getServerSupabase() {
const cookieStore = await cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll();
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
);
},
},
}
);
}
Cette séparation est propre : Payload possède le contenu. Supabase possède les données d'application et l'identité de l'utilisateur. Ils partagent la même instance PostgreSQL mais restent dans leurs champs respectifs.
Stratégie de migration : Quitter Strapi sans perdre la tête
Je ne vais pas sugarcoater cela -- la migration demande du travail. Mais c'est dramatiquement moins douloureux qu'une mise à niveau de Strapi v4 vers v5, car vous passez à un système qui respecte vos modèles mentaux existants.
Approche étape par étape
- Auditez vos types de contenu Strapi. Exportez-les en JSON à partir du Content-Type Builder. Mappez chacun à une configuration de collection Payload.
- Configurez Payload dans un nouveau projet Next.js. Exécutez
npx create-payload-app@latestet sélectionnez l'adaptateur PostgreSQL. - Pointez Payload vers votre base de données Supabase. Créez un nouveau projet Supabase, récupérez la chaîne de connexion, configurez l'adaptateur.
- Recréez les schémas en TypeScript. C'est le gros du travail. Chaque type de contenu Strapi devient une collection Payload. Les champs se mappent presque 1:1 -- texte, nombre, richtext, relation, média.
- Exportez les données de Strapi. Utilisez
pg_dumpsi vous étiez sur PostgreSQL, ou écrivez un script par rapport à l'API REST Strapi pour extraire tout le contenu. - Importez dans Payload. Utilisez l'API locale de Payload dans un script seed pour créer en masse du contenu.
- Mettez à jour votre frontend. Remplacez les appels API Strapi par des appels API locale Payload (dans les composants serveur) ou des appels REST/GraphQL (dans les composants client).
- Déployez. Puisque Payload s'exécute à l'intérieur de Next.js, vous déployez une seule application au lieu de deux.
Pour les migrations complexes, notre équipe de développement CMS headless peut aider à planifier la transition. Nous l'avons fait assez de fois pour savoir où se trouvent les pièges.
Benchmarks de performance et chiffres du monde réel
Voici les chiffres qui importent, rassemblés à partir des benchmarks publiés et de nos propres tests en 2025 :
| Métrique | Strapi v5 | Payload 3.x | Payload + Supabase |
|---|---|---|---|
| Temps de démarrage à froid | 500-2000ms | 100-300ms | 150-350ms |
| Requête simple (élément unique) | 45-80ms | 8-15ms | 10-20ms |
| Requête complexe (peuplée, 3 niveaux) | 200-500ms | 30-80ms | 40-100ms |
| Chargement du panneau d'administration | 2-4s | 1-2s | 1-2s |
| Temps de construction (500 pages, ISR) | N/A (séparé) | 45-90s | 50-100s |
| Latence mondiale (pas de CDN) | 200-500ms | 50-150ms | 60-160ms |
Le connection pooler Supabase ajoute une petite surcharge par rapport à une connexion PostgreSQL directe, généralement 5-15ms. C'est négligeable en pratique.
Une mise en garde : les requêtes de champ peuplées de Payload (résolution profonde des relations) ont été signalées comme plus lentes que les requêtes de base de données brutes -- environ 15x plus lentes que les appels directs Mongoose/Drizzle selon le problème GitHub #11325. Pour les pages à lecture intensive, je recommande d'utiliser ISR Next.js ou de mettre en cache les résultats peuplés plutôt que de frapper la base de données à chaque requête.
Quand cette pile n'est pas le bon choix
Je vous ferais du tort si je ne mentionnais pas les scénarios où Payload + Supabase est overkill ou simplement mauvais.
- Votre équipe n'écrit pas TypeScript. Payload est code-first. Si votre équipe de contenu gère tout et que vous n'avez pas de développeurs maintenant le CMS, la GUI de Strapi est genuinely meilleure. Ou regardez Sanity ou Contentful.
- Vous avez besoin d'un écosystème de plugin massif dès aujourd'hui. L'écosystème de Payload croît mais il est plus petit que les 100+ extensions de Strapi. Si vous avez besoin d'une intégration spécifique qui existe comme un plugin Strapi mais pas pour Payload, prenez en compte le temps de construction.
- Vous construisez un simple blog ou un site marketing. Strapi fonctionne bien pour cela. Tout comme Astro avec un CMS headless. Ne sur-ingénierie pas.
- Vous avez besoin de performance edge-first. Si une latence mondiale inférieure à 50ms est une exigence stricte, regardez SonicJS sur Cloudflare Workers. Payload s'exécute sur Node.js -- c'est rapide, mais ce n'est pas native aux edge.
Vous voulez discuter si cette migration a du sens pour votre projet spécifique ? Contactez-nous -- nous vous donnerons une évaluation honnête, pas un pitch de vente.
FAQ
Payload CMS est-il vraiment gratuit ?
Oui. Payload est sous licence MIT et gratuit à auto-héberger sans restrictions de fonctionnalités. Il y a un service d'hébergement optionnel Payload Cloud pour les équipes qui ne veulent pas gérer l'infrastructure, mais toutes les fonctionnalités du CMS -- aperçu en direct, contrôle d'accès, localisation, versioning -- sont disponibles dans la version open-source. Comparez cela à Strapi, qui enferme l'aperçu en direct et l'historique du contenu derrière le plan Growth à 45 $/mois.
Puis-je utiliser Supabase comme CMS en soi ?
Techniquement, vous pourriez construire une interface de gestion de contenu au-dessus de Supabase en utilisant ses APIs auto-générées et la sécurité au niveau des lignes. Mais vous reconstruiriez ce que Payload vous donne immédiatement : un panneau d'administration, l'édition de texte enrichi, la gestion des médias, le versioning du contenu et le contrôle d'accès. Supabase est une plateforme backend, pas un CMS. Utilisez-le pour ce qu'il fait bien -- hébergement de base de données, auth, stockage -- et laissez Payload gérer la couche de contenu.
Combien de temps prend la migration de Strapi à Payload ?
Pour un projet typique avec 10-20 types de contenu et quelques milliers d'entrées, compter 2-4 semaines de temps développeur. La récréation du schéma est le plus gros élément -- traduire les types de contenu Strapi en configs TypeScript Payload. La migration des données est généralement un jour ou deux avec un bon script. Les mises à jour du frontend dépendent de la façon dont votre code est étroitement couplé au format de réponse de l'API Strapi. Les équipes qui ont utilisé une couche d'accès aux données ou une abstraction auront plus de facilité.
Payload fonctionne-t-il avec des bases de données autres que PostgreSQL ?
Payload supporte à la fois MongoDB et PostgreSQL via des adaptateurs de base de données officiels. Pour la pile Supabase décrite dans cet article, vous utiliseriez l'adaptateur PostgreSQL. Si vous venez d'un background MongoDB, l'adaptateur MongoDB de Payload est en fait plus mature car MongoDB était la base de données originale de Payload. Les deux sont prêts pour la production en 2025.
Qu'en est-il de Directus comme alternative à Strapi ?
Directus est une option solide, surtout si vous avez une base de données SQL existante que vous voulez exposer via une interface CMS. Il génère automatiquement un panneau d'administration et des APIs à partir de votre schéma de base de données, ce qui est intelligent. Le principal inconvénient par rapport à Payload est le manque d'intégration profonde Next.js -- Directus s'exécute comme un service séparé, similaire à Strapi. Si votre équipe n'est pas sur la pile Next.js/Vercel, Directus mérite une sérieuse considération.
Puis-je déployer Payload + Supabase sur Vercel ?
Absolument -- c'est en fait la cible de déploiement idéale. Puisque Payload s'exécute à l'intérieur de votre application Next.js, le déploiement sur Vercel est aussi simple que de pousser vers votre repo Git. Supabase s'exécute comme un service géré, donc il n'y a rien à déployer de ce côté. Votre infrastructure totale devient : Vercel pour le calcul et le CDN, Supabase pour la base de données et l'auth. Deux services, un pipeline de déploiement. Nous configurons fréquemment cela pour les clients via notre pratique de développement Next.js.
Le panneau d'administration Payload est-il personnalisable ?
Très. L'interface utilisateur d'administration est construite avec React et supporte les composants personnalisés, les vues personnalisées et les champs personnalisés. Vous pouvez ajouter des widgets de tableau de bord, créer des éléments de navigation personnalisés et remplacer n'importe quel élément d'interface utilisateur par défaut. Depuis Payload 3.x, la personnalisation de l'administration utilise React Server Components, ce qui signifie que votre code d'administration personnalisé peut récupérer des données côté serveur sans appels API. C'est un monde différent du système d'extension d'administration de Strapi, qui nécessite d'éjecter et de patcher.
Quel est le coût d'exécution de cette pile en production ?
Pour un petit à moyen projet : Vercel Pro à 20 $/mois + Supabase Pro à 25 $/mois = 45 $/mois total. Cela vous donne le calcul serverless, une base de données PostgreSQL gérée avec 8GB de stockage, 250MB de stockage de fichiers, 50 000 utilisateurs d'authentification actifs mensuels et des sauvegardes automatiques. Augmentez-vous à partir de là selon vos besoins. Comparez cela à l'auto-hébergement de Strapi sur un VPS (20-50 $/mois) plus la gestion de votre propre base de données, ou le plan Growth de Strapi Cloud à 45 $/mois avec des sièges limités. La combinaison Payload + Supabase est compétitive en termes de coût et dramatiquement plus facile à opérer. Pour les estimations de projets détaillées, consultez notre page de tarification.