Introduction
Payload CMS est un CMS headless TypeScript-first qui s'intègre nativement à Next.js. Contrairement aux solutions no-code, il permet un contrôle total via du code. Ce tutoriel expert vous guide à travers une architecture production-ready incluant collections complexes, middlewares d'accès et optimisations de performances. Vous apprendrez à structurer un projet scalable tout en maintenant la sécurité et la maintenabilité.
Prérequis
- Node.js 20+ et npm 10+
- Next.js 15 avec TypeScript strict
- Connaissances avancées de PostgreSQL
- Docker pour les environnements de production
Initialisation du projet
npx create-next-app@latest . --yes
npm install payload @payloadcms/next @payloadcms/db-postgres @payloadcms/richtext-lexicalCette commande initialise un projet Next.js 15 et installe les dépendances Payload CMS essentielles pour une intégration App Router.
Configuration Payload de base
import { buildConfig } from 'payload/config'
import { postgresAdapter } from '@payloadcms/db-postgres'
import { lexicalEditor } from '@payloadcms/richtext-lexical'
export default buildConfig({
serverURL: process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:3000',
admin: { user: 'users' },
collections: [],
editor: lexicalEditor({}),
db: postgresAdapter({ pool: { connectionString: process.env.DATABASE_URL } }),
typescript: { outputFile: './payload-types.ts' },
})Ce fichier définit la configuration centrale. L'adaptateur PostgreSQL et l'éditeur Lexical sont configurés pour la production avec typage strict.
Création d'une collection Posts avancée
import { CollectionConfig } from 'payload/types'
export const Posts: CollectionConfig = {
slug: 'posts',
admin: { useAsTitle: 'title' },
access: { read: () => true, create: ({ req }) => !!req.user },
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'content', type: 'richText' },
{ name: 'author', type: 'relationship', relationTo: 'users' }
],
hooks: { beforeChange: [({ data }) => { data.slug = data.title.toLowerCase().replace(/\s+/g, '-'); return data }] }
}Collection complète avec contrôle d'accès, relation et hook de génération de slug. Le hook s'exécute avant chaque modification pour maintenir la cohérence des données.
Implémentation du contrôle d'accès granulaire
import { Access } from 'payload/config'
export const isAdmin: Access = ({ req: { user } }) => {
if (!user) return false
return user.roles?.includes('admin') || false
}Fonction d'accès réutilisable qui vérifie le rôle admin. Elle protège les opérations sensibles et s'intègre dans toutes les collections.
Route API Payload dans Next.js
import { GET, POST, PATCH, DELETE } from '@payloadcms/next'
import config from '@/payload.config'
export { GET, POST, PATCH, DELETE }
export const runtime = 'nodejs'Route catch-all qui expose l'API REST et GraphQL de Payload. Le runtime Node est obligatoire pour les opérations de base de données.
Bonnes pratiques
- Toujours typer les collections avec payload-types.ts généré
- Utiliser des hooks beforeChange pour la validation métier
- Séparer les accès en fichiers réutilisables
- Activer les index PostgreSQL sur les champs filtrés fréquemment
- Versionner les migrations de schéma en production
Erreurs courantes à éviter
- Oublier de régénérer les types après modification de collections
- Utiliser des relations sans index, causant des lenteurs
- Négliger les hooks async qui peuvent bloquer les requêtes
- Exposer des champs sensibles sans contrôle d'accès précis
Pour aller plus loin
Approfondissez vos compétences avec nos formations Payload CMS avancées.