Hier à 22h j'avais une idée vague de transformer un déploiement Directus en asset de vente. Ce matin à 7h j'avais un admin opérationnel sur Railway, trois dashboards en direct, un blog de démo public avec cinq articles, un article pilier de 2 400 mots qui présente l'ensemble comme un service, et trois bugs de production que j'ai détectés et corrigés à minuit. Le coût infrastructure total : 5 $ par mois. Le temps total : environ neuf heures de travail concentré réparties sur une nuit et une matinée.
Ceci est le cas d'usage. Ce qui a été construit, ce qui s'est cassé, ce que j'ai appris, et les vrais chiffres derrière le build. Si vous évaluez la possibilité de commander un projet similaire pour votre entreprise, les points de données ci-dessous sont la référence la plus honnête que je puisse offrir.
Ce que je me suis fixé comme objectif
Trois objectifs, par ordre de priorité.
D'abord, déployer Directus connecté à ma base de données Postgres Supabase existante. Objectif : un admin CRUD générique pointant vers les mêmes données que mon admin Astro personnalisé gère déjà. Raison : non pas remplacer l'admin personnalisé (qui a l'édition inline de style Monday que l'équipe aime), mais ajouter la couche opérationnelle que l'admin personnalisé n'a pas. Éditions en masse, vues sauvegardées, permissions basées sur les rôles, navigateur de schéma, dashboards Insights.
Deuxièmement, mettre en place les tableaux de bord que je voulais depuis six mois. Trois tableaux : pipeline de contenu (vélocité de publication des blogs, profondeur de la queue de sujets), santé SEO (positions de classement, taux de présence dans les AI Overviews, distribution des intentions), utilisation des outils (recherches d'outils AEO, recherches d'outils de marque, utilisation des conseillers). Des chiffres concrets que je peux consulter le lundi pour savoir si le moteur tourne.
Troisièmement, transformer toute la build en actif commercial. L'admin Directus que je déploie pour moi-même est identique à celui que je déploierais pour un client. Le déploiement lui-même devient donc la démo. Un prospect clique sur un bouton de ma page de vente, arrive dans un vrai admin Directus rempli de vraies données, tape dans l'éditeur de texte enrichi, voit comment fonctionnent les vues enregistrées, puis revient pour réserver un appel. Friction totale de la boucle de démo : environ quinze secondes entre l'arrivée sur la page et l'accès à l'éditeur live.
Heure 0 à 4 : déployer
Plan hobby Railway, template officiel Directus, déploiement en un clic. Le template est livré avec Directus plus Redis plus une base de données PostGIS intégrée plus un bucket de stockage compatible S3. Temps de déploiement total incluant la configuration : 35 minutes à partir d'un compte Railway vierge jusqu'à l'admin connecté.
La première surprise : le template Directus câble sa connexion à la base de données via des variables de référence pointant vers le service PostGIS intégré, non via des champs host/port/user/password individuels. Pour rediriger Directus vers mon Postgres Supabase externe, j'ai dû trouver la variable de chaîne de connexion (DB_CONNECTION_STRING) et coller mon URL Supabase Session pooler avec les identifiants.
La deuxième surprise : mon mot de passe Supabase contenait le caractère « # ». Encodé en URL sous la forme %23 dans une chaîne de connexion Postgres. Sans encodage, l'analyseur d'URL coupe la chaîne au # car le hash signifie fragment d'URL. Directus a enregistré ECONNREFUSED::1:5432 car il a basculé vers localhost quand la chaîne de connexion était malformée. Une demi-heure de confusion, puis j'ai fait pivoter le mot de passe sur alphanumériques uniquement et la connexion s'est établie.
Une fois Directus connecté, les 12 tables de ma base de données Supabase se sont auto-importées en tant que Collections Directus. Zéro migration de schéma, zéro mouvement de données, zéro temps d'arrêt. L'admin Astro personnalisé et l'admin Directus voient tous deux les mêmes données, écrivent tous deux dedans, reflètent immédiatement les changements de l'autre.
Heure 4 à 12 : configurer, configurer, configurer
L'essentiel du travail n'était pas le déploiement. C'était la configuration au niveau des champs pour que Directus se comporte comme un admin poli plutôt que comme un navigateur de base de données brut. Chaque colonne a besoin de métadonnées d'interface, de formatage d'affichage, d'ordre de tri, de largeur, de groupe et de décisions de visibilité. Directus par défaut affiche tout ; la version polie affiche seulement ce dont l'équipe a besoin.
Trois observations de cette phase.
Faire cela via l'interface d'administration Directus en cliquant, c'est lent. Environ deux minutes par champ, quatre-vingt-dix champs et plus répartis sur douze collections, le temps de clic total près de trois heures. J'ai confié la tâche à un agent IA pilotant un navigateur (Claude dans Chrome) qui a basculé vers l'API REST de Directus pour une configuration en masse. L'agent a publié des appels PATCH /fields/{collection}/{field} en séquence, avec l'objet meta complet en tant que payload. Trois minutes par collection au lieu de quarante. Toute la phase de configuration compressée de trois heures à quarante minutes.
L'approche par API REST m'a aussi donné de la reproductibilité. Chaque PATCH est équivalent à une commande curl que je pourrais relancer sur un déploiement Directus vierge pour restaurer la même configuration. La configuration est effectivement du code, pas un tas fragile de clics d'interface.
Le dernier quart de cette phase était la construction des trois tableaux de bord Insights. Chaque panneau est une config JSON envoyée en POST /panels. Les tableaux de bord ont été livrés en environ vingt minutes une fois les métadonnées de champ en place. Trois tableaux, six panneaux, données réelles s'affichant. Les chiffres sur lesquels je devinais depuis six mois étaient enfin à l'écran.
Heure 12 à 18 : les trois bugs qui ont pris le plus de temps
Aucun build n'est réel tant qu'il ne casse pas en production. Trois bugs ont surgi après que j'ai poussé vers main et rafraîchi le site en direct.
Bug 1 : scène Spline bloquée par CSP, avec trois causes imbriquées
J'avais aussi livré un pilier web en 3D d'abord avec un robot héros NEXBOT Spline. Après le déploiement, le robot était invisible en production mais fonctionnait localement. Trois problèmes imbriqués en séquence.
Un : la balise script utilisant define:vars a été inlinée par Astro, ce qui signifiait que Vite ne bundlait pas l'import dynamique de @splinetool/viewer, ce qui signifiait que le spécificateur de module nu était non-résolvable dans le navigateur. Deux : après correction, l'élément spline-viewer était à l'intérieur d'un parent avec l'attribut hidden au moment de la mise à niveau, donc l'élément personnalisé Lit s'est initialisé avec des dimensions 0x0 et ne s'est jamais rétabli. Trois : après correction, le visualiseur Spline récupère son WASM de modélisation depuis unpkg.com au moment du chargement de la scène, que ma CSP n'avait pas mise en liste blanche. Chaque correction a révélé le bug suivant. Temps de débogage total : quatre-vingt-dix minutes.
Le débogage en production uniquement est sa propre discipline. Le serveur de développement résout les imports nus différemment du build de production. L'environnement de développement a une CSP par défaut plus permissive. Les deux bugs étaient impossibles à révéler sans un déploiement en production réel. Mon enseignement : déployez dans un environnement réel tôt, même quand l'exécution locale fonctionne bien.
Bug 2 : booléen AI Overview et Postgres avg()
Un panneau Insights voulait afficher « quel pourcentage des exécutions SERP suivies affichent un AI Overview ». La table seo_serp_runs possède une colonne booléenne ai_overview_present. Instinct naïf : faire avg() sur cette colonne, multiplier par 100, afficher en pourcentage.
Postgres lève une erreur sur avg(boolean). La fonction n'existe pas pour ce type. Plusieurs tentatives de contournement ont échoué : Directus n'expose pas d'agrégat « percentage », un count-of-true avec dénominateur codé en dur s'écarte à mesure que de nouvelles lignes arrivent, le cast au moment de la requête n'est pas exposé via les options du panneau Insights.
La correction qui a fonctionné : ajouter une colonne générée ai_overview_present_int qui se calcule comme case when ai_overview_present then 100 else 0 end. avg() sur une colonne entière fonctionne trivialement et donne le pourcentage directement. Migration SQL sur une ligne, zéro changement au code applicatif.
Bug 3 : les hôtes d'images dans la CSP
J'ai alimenté le blog de démo avec cinq URLs de photos Unsplash. Le navigateur les a bloquées silencieusement parce que images.unsplash.com n'était pas whitelisté dans img-src. Des cartes d'images noires sur le blog de démo public. J'ai ajouté Unsplash à la CSP, les images se sont affichées, puis j'ai réalisé que je venais de violer ma propre règle non négociable d'utiliser FAL pour toutes les images stockées dans Supabase Storage.
Correction adéquate : un script qui récupère chaque ligne demo_posts, génère une photographie éditoriale par catégorie via FAL flux-pro/v1.1-ultra, ré-encode avec sharp en WebP à qualité 82 max-width 1600, envoie vers un bucket Supabase Storage public, met à jour featured_image vers l'URL CDN du stockage. Build de vingt minutes, cinq générations FAL coûtent moins d'une livre. Suppression d'Unsplash de la CSP. Les images vivent désormais sur ma propre infrastructure, zéro dépendances externes, zéro tapis roulant de mise à jour CSP-par-hôte à l'avenir.
Heure 18 à 24 : le pilier commercial
Avec Directus opérationnel et le blog de démo se rendant correctement, j'ai rédigé le pilier commercial sur /solutions/headless-cms-and-admin-tools/. Quatre étages de services (CMS, admin ops interne, répertoires, sur mesure), tarifés en USD avec GBP entre parenthèses, six FAQs, un tableau de comparaison face à WordPress et HubSpot et Notion et Airtable, une section « brief que je ne prendrai pas » pour disqualifier les clients de mauvaise forme dès le départ.
Le pilier se lie directement à la démo en direct. Les prospects cliquant « OPEN THE EDITOR » arrivent dans l'admin Directus réel avec des identifiants affichés qu'ils collent. Quelques secondes plus tard ils éditent un vrai post dans un vrai éditeur. La boucle de démo prend quinze secondes du chargement de la page à l'édition en direct.
Temps total sur la page du pilier : quatre-vingt-dix minutes d'écriture plus trente minutes de balisage de schéma, de liens internes et de finition visuelle. La page elle-même a pris moins de temps que deux des trois bugs.
Chiffres
Ventilation des coûts de construction, puisqu'il s'agit du post d'étude de cas et c'est la question que les prospects poseront.
Plan Railway Hobby pour Directus + Redis + bucket : 5 $ par mois, facturé mensuellement. Premiers 30 jours gratuits.
Supabase Postgres : infrastructure existante, aucun coût nouveau. Utilisation du plan Pro déjà en place à environ 25 $ par mois pour la base de données.
API FAL pour cinq images hero : moins d'une livre sterling au total, environ 1 $ USD.
DataForSEO pour remplir 42 mots-clés avec volume de recherche + intention + difficulté : 0,04 $ au total.
Mon temps, de bout en bout incluant les bugs et la rédaction : neuf heures de travail concentré. À mon taux journalier de conseil d'environ 1 500 $ par jour, cela représente environ 1 700 $ de coût d'opportunité.
Dépense en espèces totale pour livrer l'actif de vente fonctionnel : environ 6 $ d'infrastructure marginale plus 1 $ de frais API. Coût réel total incluant le temps : environ 1 700 $.
Comparaison de référence : une agence citant un engagement de construction d'« outil d'administration de CMS headless » facturerait généralement entre 8 000 et 15 000 $ USD pour une portée équivalente. Je facture entre 8 000 et 19 000 $ USD sur ma propre page de service. L'écart entre le coût de construction et le prix de vente est tout le moteur économique du travail en agence. L'étude de cas est la preuve que le chiffre du coût de construction est réel.
Ce que cela prouve à un client prospect
Trois choses, toutes vérifiables en dix minutes.
D'abord, la construction est réelle. Cliquez sur le bouton OPEN THE EDITOR sur la page de vente. Tapez dans l'éditeur de texte enrichi. Planifiez un article. Regardez les tableaux de bord. La chose existe. Ce n'est pas une maquette, ce n'est pas un fichier Figma, ce n'est pas une capture d'écran. C'est le même logiciel que je déploierais pour votre entreprise.
Deuxièmement, la rapidité est réelle. Vingt-quatre heures de « idée vague » à « actif de vente déployé en production avec démo en direct ». Un engagement client ne se déplacerait pas à cette vitesse car les engagements clients incluent la découverte, l'examen du design, les approbations des parties prenantes et les audits de sécurité. Mais la vélocité de construction sous-jacente est ce qui détermine si un délai de six semaines est honnête ou optimiste. Vingt-quatre heures d'effort de construction solo correspondent à environ trois semaines de temps d'engagement d'agence standard une fois que les frais généraux sont intégrés. C'est cette mathématique qui produit le délai de six à huit semaines du tier-1.
Troisièmement, les modes de défaillance sont réels. Trois bogues de production ont été détectés et corrigés en temps réel. Problèmes de CSP, bundling d'importation dynamique, arithmétique de colonne générée. Ce sont les mêmes bogues qui apparaissent dans les engagements clients. Le fait que je les ai détectés et résolus sur un site en direct est la démonstration réelle de compétence. Une étude de cas polie sans bogues serait la suspecte.
Ce que je ferais différemment
Trois petites réflexions, par ordre d'utilité.
J'aurais commencé par le script de génération d'image FAL avant le contournement Unsplash. La danse de mise à jour-puis-rétablissement de CSP a coûté dix minutes de churn inutile. La règle non négociable concernant les images FAL existe précisément pour cette raison et j'aurais dû l'écouter d'abord.
J'aurais utilisé l'approche REST API pour la configuration de Directus dès le départ au lieu d'essayer le clic dans l'interface utilisateur. La séquence d'appels REST pilotée par l'agent était trois fois plus rapide et a produit une configuration reproductible. La leçon se généralise au-delà de Directus : tout admin qui expose une API REST complète doit être configuré via cette API plutôt que via son interface utilisateur.
J'aurais écrit le article de l'étude de cas plus tôt. Cet article est écrit environ douze heures après la fin de la construction. Au moment où j'écris ceci, certains des modes de défaillance s'estompent déjà de la mémoire. L'étude de cas honnête est celle écrite le même jour que la construction, alors que les bogues sont assez frais pour être décrits avec précision.
Où aller ensuite
Si vous évaluez si votre entreprise devrait commander un développement similaire, la boucle de démonstration est le chemin le plus rapide vers une réponse utile. Ouvrez /solutions/headless-cms-and-admin-tools/, cliquez sur le bouton de démonstration, connectez-vous avec les identifiants affichés, passez quinze minutes à explorer. À la fin, vous aurez une idée claire de savoir si ce type d'outil convient à votre équipe ou non.
Si oui, réservez l'appel de trente minutes lié sur cette page. Décrivez-moi votre stack existant, la taille de votre équipe, votre structure de données. À la fin de l'appel, vous avez choisi un tier, une plage de prix et une fenêtre de livraison. La plupart des engagements que j'accepte durent six à douze semaines entre 8 000 et 50 000 USD selon le scope. La moitié que je refuse, je vous explique pourquoi durant l'appel.
Si vous voulez le pitch de vente complet, la pillar page se trouve à /solutions/headless-cms-and-admin-tools/. Si vous voulez passer directement à la démonstration en direct, les identifiants sont sur cette page. Si vous voulez la prochaine étude de cas, le prochain article de blog parlera probablement soit d'un développement pour un fabricant du corridor asiatique, soit du même pattern appliqué à un vertical différent. Dites-moi lequel est plus utile.
