Introduction
Un Headless CMS sépare le contenu de la présentation, offrant une flexibilité totale pour les développeurs. Strapi 5, avec son support natif de TypeScript, permet de créer des API robustes et sécurisées. Ce tutoriel vous guide à travers une configuration avancée incluant des types de contenu complexes, des middlewares personnalisés et un déploiement optimisé. Vous apprendrez à éviter les pièges courants tout en suivant les standards de production.
Prérequis
- Node.js 20+ et npm/yarn
- Connaissances solides en TypeScript et REST/GraphQL
- Compte sur un hébergeur (Vercel, Railway ou VPS)
- Strapi 5 CLI installé globalement
Initialisation du projet Strapi
npx create-strapi-app@latest my-cms --quickstart --ts
cd my-cms
npm run developCette commande crée un projet Strapi 5 avec TypeScript activé par défaut. Le flag --quickstart lance une base SQLite pour le développement rapide.
Création du type de contenu Article
{
"kind": "collectionType",
"collectionName": "articles",
"info": {
"singularName": "article",
"pluralName": "articles",
"displayName": "Article"
},
"options": {
"draftAndPublish": true
},
"attributes": {
"title": {
"type": "string",
"required": true
},
"content": {
"type": "richtext"
},
"slug": {
"type": "uid",
"targetField": "title"
}
}
}Le fichier schema.json définit le modèle Article. Le champ uid génère automatiquement des slugs uniques à partir du titre.
Configuration des permissions API
export default {
rest: {
defaultLimit: 25,
maxLimit: 100,
withCount: true,
},
response: {
status: 200,
headers: {
'Cache-Control': 'public, max-age=300',
},
},
};Ce fichier ajuste les limites par défaut et ajoute des en-têtes de cache. Cela améliore les performances des requêtes publiques tout en restant sécurisé.
Ajout d'un controller personnalisé
import { factories } from '@strapi/strapi';
export default factories.createCoreController('api::article.article', ({ strapi }) => ({
async findBySlug(ctx) {
const { slug } = ctx.params;
const article = await strapi.db.query('api::article.article').findOne({
where: { slug },
populate: ['author'],
});
if (!article) return ctx.notFound();
return article;
},
}));Ce controller ajoute une route personnalisée /articles/slug/:slug. Il utilise le query builder pour des performances optimales avec population des relations.
Intégration Next.js avec fetch typé
export async function getArticle(slug: string) {
const res = await fetch(`${process.env.STRAPI_URL}/api/articles/slug/${slug}`, {
headers: { Authorization: `Bearer ${process.env.STRAPI_TOKEN}` },
next: { revalidate: 300 },
});
return res.json();
}
export default async function ArticlePage({ params }: { params: { slug: string } }) {
const data = await getArticle(params.slug);
return <h1>{data.title}</h1>;
}Ce code Next.js récupère les données de Strapi avec revalidation ISR. Utilisez des variables d'environnement pour les tokens afin de sécuriser l'accès.
Bonnes pratiques
- Toujours activer draftAndPublish pour les contenus critiques
- Utiliser des middlewares pour la validation et la sanitization
- Configurer des limites de requêtes strictes en production
- Versionner vos content-types avec des migrations
- Activer les logs structurés pour le monitoring
Erreurs courantes à éviter
- Oublier de régénérer les types TypeScript après modification du schéma
- Laisser les permissions publiques trop permissives
- Ignorer la configuration CORS pour les origines frontend
- Ne pas configurer de backup automatique de la base de données
Pour aller plus loin
Approfondissez vos compétences avec nos formations avancées sur les Headless CMS.