Développement Web

Directus 2026 : guide complet (headless CMS open source pour PME africaine)

11 دقائق للقراءة

Vous avez une équipe non-technique (rédacteurs, marketing, e-commerce manager) qui a besoin de gérer des contenus, et une équipe technique qui veut une API moderne pour les afficher dans Next.js, Astro, ou app mobile. Strapi à 99 USD/mois Cloud, Contentful à 489 USD/mois, Sanity à 99 USD/mois après 3 utilisateurs. Directus est le headless CMS open source qui s’est imposé en 2026 (informations vérifiées en avril 2026, susceptibles d’évoluer) chez les agences digitales et e-commerces francophones d’Afrique de l’Ouest et du Maghreb : interface admin intuitive, API REST + GraphQL + SDK auto-générées depuis votre schema Postgres ou MySQL, permissions granulaires, workflows. Auto-hébergé sur Hetzner CX23 à 4,51 €/mois pour usage illimité.

Sommaire

Pourquoi Directus domine en 2026

Quatre raisons concrètes expliquent l’adoption massive.

Database-first. Contrairement à Strapi (qui crée sa propre structure), Directus se branche sur une base existante (PostgreSQL, MySQL, SQLite, MariaDB). Vous pouvez exposer une base legacy en API moderne sans refactor. Pour une PME avec un ERP custom et 5 ans de données, c’est révolutionnaire.

API auto-générées. REST, GraphQL, et SDK JavaScript/TypeScript sont générées automatiquement depuis votre schéma. Aucun code à écrire pour exposer une nouvelle table.

UI excellente. Studio Directus rivalise avec Contentful en UX : édition rich text TinyMCE, drag-and-drop pour réordonner, filtres puissants, vues custom (Kanban, calendrier, carte, gallerie). Les rédacteurs apprennent en 1 heure.

Permissions granulaires. Au niveau collection, item, ou champ. Un rédacteur peut éditer le titre mais pas le statut. Un comptable peut lire mais pas modifier. Workflow simple.

Concepts fondamentaux

Collections, fields, items

Une collection = une table SQL. Un field = une colonne. Un item = une ligne. Directus expose tout cela en API REST/GraphQL avec relations gérées.

Roles et permissions

Roles : Admin, Editor, Reviewer, Public, etc. Pour chaque rôle, permissions par collection (read, create, update, delete) et par champ. Filters dynamiques (« Editor peut update uniquement ses propres items »).

Flows et automations

Workflows visuels via drag-and-drop : trigger (item created, scheduled, webhook) → operations (update field, send email, call webhook, run script). Équivalent n8n mais natif dans Directus.

Webhooks et real-time

Sur tout event (item.create, item.update), webhook envoyé à URL externe. Pour update Next.js ISR, déclencher build Vercel/Netlify, notifier Slack.

Files et assets

Stockage S3-compatible (MinIO, Backblaze, AWS) via driver. Image transformations à la volée (resize, crop, compress) sans plugins externes.

Translations et i18n

Champs multilingues out-of-the-box. Un produit peut avoir title_fr, title_ar, title_en via Translations interface.

Vue d’ensemble pratique

1. Déploiement

Coolify + template Directus + Postgres. 30 minutes setup. Voir Déployer Directus sur Coolify.

2. Modélisation des données

Créer collections via Studio admin : Products, Articles, Authors, Categories. Fields, relations, validations. Voir Modélisation collections et relations.

3. Frontend Next.js / Astro

Consommer l’API Directus via SDK ou GraphQL. Voir Connecter Directus à Next.js et Astro.

4. Roles et workflow éditorial

Configurer rôles Reviewer, Editor, Admin. Workflow draft → review → published. Voir Roles permissions et workflow éditorial.

Tutoriels du cluster Directus

Cas d’usage

E-commerce headless

Marketplace à Dakar avec Next.js front-end + Directus back. Catalogue 8 000 produits, 12 catégories, multi-vendeurs. Rédacteurs gèrent depuis Studio, frontend API. Performance excellente, latence p95 < 100 ms.

Site éditorial multilingue

Média digital à Casablanca : articles en français + arabe + anglais. Champs translations Directus. SEO optimal sur les 3 langues.

Annuaire professionnel

Annuaire de 2 000 entreprises tech ouest-africaines : champs custom (secteur, ville, taille, fondateur), filtres puissants côté API, recherche full-text via PostgreSQL FTS.

Catalogue immobilier

Agence immo à Tunis : 600 biens avec 20+ champs (m², chambres, prix, géo, photos). Frontend Astro statique avec build incrémental sur webhook Directus.

Documentation produit (sans code)

SaaS à Abidjan : Directus stocke FAQ, guides, changelog. Frontend Astro consomme via GraphQL au build. Équipe support édite sans demander aux devs.

Considérations propres à l’écosystème sous-régional

Quatre adaptations spécifiques.

Coût. Strapi Cloud (89 USD/mois) ou Contentful (489 USD/mois) vs Directus self-hosted Hetzner CX23 (4,51 €/mois). Économies de 1 000 à 5 000 USD/an pour un projet PME.

Multilingue FR/AR. Pour un site servant Maroc, Tunisie, Algérie, Liban, Émirats : Directus translations gèrent FR + AR + EN nativement. Schéma propre, pas de duplications.

Storage local. MinIO sur même VPS pour photos catalogue. Pas de transfert hors Afrique de l’Ouest. Latence < 50 ms pour servir images mobile.

Connexion intermittente Studio admin. Studio Directus PWA : éditeurs peuvent rédiger offline, sync au retour réseau. Crucial pour journalistes sur le terrain.

Erreurs fréquentes

Erreur Cause Solution
API REST 401 Unauthorized Public role pas configuré Settings → Roles → Public → activer permissions read
Images ne s’affichent pas Storage S3 mal configuré Vérifier credentials + bucket public read
Performance frontend lente Pas de cache CDN Cloudflare devant + Cache-Control headers
GraphQL queries N+1 Relations pas en deep populate Utiliser ?fields=*,author.*
Workflow loop Flows trigger eux-mêmes Conditions filter pour break
Backup manquant Postgres pas sauvegardé Cron quotidien pg_dump + restic

FAQ

Directus vs Strapi en 2026 ? Directus database-first (idéal pour bases existantes), Strapi schema-first (idéal pour greenfield). UI Directus plus moderne. Tarification gratuite équivalente.

Combien d’utilisateurs admin Studio max ? Hetzner CX23 = 50 admins simultanés. Au-delà CCX13.

Est-ce qu’on peut écrire dans la DB en bypass Directus ? Oui. Directus se synchronise au prochain cache flush. Migration scripts utilisent souvent direct SQL.

SDK TypeScript ? Oui, types auto-générés depuis schéma. @directus/sdk.

Compatible Drizzle ORM ? Oui, Drizzle + Directus se mariant parfaitement. Drizzle pour writes côté backend, Directus pour reads.

Real-time updates ? Oui, WebSocket et Server-Sent Events. Frontend reactive sans polling.

Multi-tenant ? Pas natif. Workaround : un Directus par tenant ou colonne tenant_id avec filter middleware.

Pour creuser ce sujet

Étape 1 : comprendre la promesse Directus pour une PME africaine

Directus est un CMS headless open source qui transforme n’importe quelle base PostgreSQL ou MySQL existante en API REST et GraphQL. Pour une PME basée à Abidjan ou Dakar qui possède déjà une base de stocks ou de clients, Directus évite la réécriture complète : on pose la couche admin et l’API sur l’existant. La licence BSL 1.1 autorise un usage commercial gratuit jusqu’à 5 millions USD de revenus, donc largement la majorité des structures locales.

# Vérifier la version Node avant de commencer
node -v
# Sortie attendue : v22.x (LTS Jod). Si v18 ou plus ancien, mettez à niveau.

Directus 11 (sorti fin 2025) requiert Node 22 LTS minimum. Sur un VPS OVH ou Contabo bon marché, installez via nvm install 22 && nvm use 22. Cette base technique conditionne tout le reste : un Node trop ancien fait échouer l’installation au premier npm install.

Étape 2 : provisionner la base PostgreSQL

PostgreSQL 16 ou 17 est le choix recommandé pour Directus en 2026. MySQL 8 fonctionne aussi mais perd certaines fonctionnalités (recherche plein texte, JSONB performant). Pour une PME, hébergez la base sur le même VPS que Directus dans un premier temps, puis séparez quand le trafic dépasse 500 visiteurs simultanés.

# Installer PostgreSQL 16 sur Ubuntu 24.04
sudo apt update && sudo apt install -y postgresql-16
sudo -u postgres psql -c "CREATE DATABASE directus_db;"
sudo -u postgres psql -c "CREATE USER directus WITH ENCRYPTED PASSWORD 'mot_de_passe_long';"
sudo -u postgres psql -c "GRANT ALL ON DATABASE directus_db TO directus;"

Le mot de passe doit faire au moins 24 caractères. Stockez-le dans un fichier .env non versionné. La sortie attendue de chaque commande est CREATE DATABASE, CREATE ROLE, GRANT. En cas d’erreur de socket, vérifiez que PostgreSQL écoute sur localhost avec sudo systemctl status postgresql.

Étape 3 : installer Directus avec Docker Compose

L’installation Docker est plus reproductible qu’une installation native. Créez un fichier docker-compose.yml qui orchestre Directus, PostgreSQL et un cache Redis. Cette configuration tient sur un VPS à 4 Go de RAM (environ 6 EUR par mois, soit 3 936 FCFA au taux fixe 1 EUR = 655,957 FCFA).

services:
  directus:
    image: directus/directus:11
    ports: ["8055:8055"]
    environment:
      KEY: "votre-cle-aleatoire"
      SECRET: "votre-secret-aleatoire"
      DB_CLIENT: "pg"
      DB_HOST: "postgres"
      DB_DATABASE: "directus_db"
      DB_USER: "directus"
      DB_PASSWORD: "mot_de_passe_long"
      ADMIN_EMAIL: "admin@votre-domaine.tld"
      ADMIN_PASSWORD: "mot_de_passe_admin"

Lancez avec docker compose up -d. La sortie liste les conteneurs en mode détaché. Après 30 secondes, accédez à http://votre-vps:8055. La page de connexion Directus s’affiche. Si elle ne charge pas, consultez docker compose logs directus pour identifier la cause (souvent une variable d’environnement manquante).

Étape 4 : créer une première collection « clients »

Une fois connecté à l’admin, allez dans Settings, Data Model, Create Collection. Nommez-la clients. Ajoutez les champs : nom (string), telephone (string), pays (dropdown SN, CI, BJ, ML, BF, TG), date_creation (datetime). Directus crée automatiquement la table SQL et expose les endpoints REST et GraphQL.

# Tester la création d'un client via l'API REST
curl -X POST http://votre-vps:8055/items/clients   -H "Authorization: Bearer VOTRE_TOKEN"   -H "Content-Type: application/json"   -d '{"nom":"Awa Diop","telephone":"+221771234567","pays":"SN"}'

La réponse attendue est un JSON avec l’id du nouvel enregistrement et les champs renvoyés. Pour obtenir le token, créez un Static Token dans le profil utilisateur de Directus. Ne committez jamais ce token dans Git ; passez-le en variable d’environnement de votre application cliente.

Étape 5 : configurer les permissions par rôle

Directus distingue deux rôles natifs (Administrator, Public) et permet d’en créer autant que nécessaire. Pour une PME, créez trois rôles : Editor (CRUD complet sur les collections de contenu), Sales (lecture clients, écriture commandes), Public (lecture seule sur le catalogue public).

// Exemple de filtre de permission pour Sales :
// Champ "owner" doit être égal à l'ID de l'utilisateur connecté
{
  "owner": { "_eq": "$CURRENT_USER" }
}

Ce filtre s’applique côté Directus avant chaque requête. Un commercial ne voit que ses propres clients, jamais ceux d’un autre commercial. Cette segmentation est cruciale pour la conformité avec la loi 2008-12 sénégalaise sur la protection des données et l’équivalent ivoirien (loi 2013-450).

Étape 6 : connecter un front Next.js ou Vue

Le front communique avec Directus via REST ou GraphQL. Pour Next.js 15, utilisez le SDK officiel @directus/sdk. Pour Vue ou Nuxt, le module nuxt-directus simplifie l’authentification et le cache.

import { createDirectus, rest, readItems } from '@directus/sdk';
const client = createDirectus('https://api.votre-domaine.tld').with(rest());
const clients = await client.request(readItems('clients', {
  filter: { pays: { _eq: 'SN' } },
  limit: 50
}));

Cette requête typée TypeScript renvoie les 50 premiers clients sénégalais. Le SDK gère automatiquement la pagination, le cache HTTP et la sérialisation. Pour le mode brouillon, ajoutez fields: ['*', 'commandes.*'] pour récupérer les relations imbriquées en une seule requête.

Étape 7 : automatiser avec les Flows

Les Flows Directus sont l’équivalent low-code de Make ou n8n, intégrés au CMS. Vous déclenchez une suite d’opérations sur un événement : nouveau client créé, commande validée, fichier uploadé. Pour une PME, automatisez l’envoi d’un SMS de bienvenue via une API locale comme InTouch ou Orange SMS API.

// Opération Webhook dans un Flow
{
  "url": "https://api.intouch.sn/v1/sms",
  "method": "POST",
  "headers": { "Authorization": "Bearer $env.INTOUCH_TOKEN" },
  "body": { "to": "{{ $trigger.payload.telephone }}", "message": "Bienvenue {{ $trigger.payload.nom }}" }
}

Le Flow s’exécute en moins de 200 ms après l’événement. Surveillez les erreurs dans Activity Log. Si l’API SMS répond 429 (rate limit), ajoutez une opération Delay de 5 secondes entre deux envois ou regroupez les notifications par lot toutes les 10 minutes.

Étape 8 : sauvegarder et superviser en production

Une PME ne peut pas se permettre de perdre 6 mois de données clients. Configurez un backup quotidien de PostgreSQL avec pg_dump envoyé sur un stockage S3 compatible (Backblaze B2, Wasabi, Scaleway Object Storage). Ajoutez Uptime Kuma ou Better Stack pour surveiller la disponibilité depuis Dakar et Paris.

# Cron job quotidien à 3 h du matin
0 3 * * * pg_dump directus_db | gzip | aws s3 cp - s3://backup-directus/$(date +\%F).sql.gz

Vérifiez chaque mois qu’une restauration fonctionne : c’est le test qui valide le backup. Sans restauration testée, vous n’avez pas de sauvegarde, vous avez de l’illusion. Conservez 30 sauvegardes quotidiennes plus 12 mensuelles minimum.

À lire ensuite, consultez notre tutoriel WooCommerce pour comparer un CMS classique à un headless, et notre guide PHP sécurisé qui s’applique aussi aux extensions Directus en custom code.

Étape 9 : optimiser les performances et le cache

Activez le cache Redis pour les requêtes fréquentes : ajoutez le service redis dans docker-compose.yml et passez CACHE_ENABLED=true, CACHE_STORE=redis dans les variables Directus. Sur un VPS basique, le gain mesuré sur une collection produits est de 80 ms en moyenne par requête, soit une expérience nettement plus fluide pour un visiteur sur 4G à Bamako ou Lomé.

CACHE_ENABLED: "true"
CACHE_STORE: "redis"
REDIS: "redis://redis:6379"
CACHE_TTL: "5m"

Le TTL de 5 minutes est un bon compromis entre fraîcheur et performance. Pour un catalogue produits qui change rarement, montez à 30 minutes ou 1 heure. Le cache se purge automatiquement à chaque mutation grâce au mécanisme d’invalidation natif de Directus.

مشاركة