Aller au contenu
Souleymane Diallo
Le métier

Entre un besoin d'affaires et une application en production, il y a trop de mains.

Développeur, analyste et concepteur — du cadrage jusqu'au déploiement.

Mon but est que ce qui arrive en production soit ce qui avait été demandé.

La pile
  • Angular
  • TypeScript
  • React
  • Next.js
  • .NET
  • NestJS
  • Python
  • FastAPI
  • PostgreSQL
  • Docker

« On rêve d'un développeur qui s'assoie avec le métier et qui en revienne avec du développable. »

« On cherche quelqu'un qui s'intègre à notre équipe et à notre pile, pas quelqu'un qui les réinvente. »

« Nos spécifications sont écrites par des gens qui ne développeront pas. On s'en aperçoit trop tard. »

« On a livré. Depuis, plus personne dans l'équipe ne veut reprendre ce code. »

J'ai vu ces situations une dizaine de fois. Elles se règlent.

Écoute active

Comprendre le besoin réel derrière les mots.

Spécifications claires

Traduire le métier en solutions concrètes.

Code propre et maintenable

Des bases solides pour aller plus loin.

Livraison durable

Un code adopté par l'équipe, pas subi.

Le travail

Ce que je fais concrètement

Quatre phases,
du cadrage au déploiement
01L'entretien
avec les utilisateurs

Je vais chercher le besoin là où il est.

Je m'assois avec ceux dont le travail va changer, pas seulement avec celui qui commande, et j'en repars avec ce qu'il faut construire et pourquoi. C'est le seul moment où une application se décide vraiment.

02Les spécifications

J'écris ce que je vais développer.

La spécification n'est pas un document que je reçois : c'est un document que je produis, en sachant que je devrai l'exécuter. Les règles de gestion y entrent avec leur date de validité.

03Le code,
en équipe

Je m'insère dans votre pile, je n'en impose pas une.

Deux écosystèmes d'interface, trois serveurs. En sprints, avec revues de code et protection des branches — le cadre posé le premier jour, pas au milieu.

04La mise
en production

Je livre, et je reste dessus.

Aucun relais à organiser après la mise en service. Je réponds encore de ce que j'ai livré six mois plus tard.

Les preuves

Ce qu'en disent les clients

Deux plateformes clientes,
vues par ceux qui les ont dirigées
Écran de connexion de la plateforme de la Minoterie du Sénégal : entrée par numéro de téléphone et code reçu.
Secteur
Meunerie industrielle
Rythme
3 équipes · 24 h · 4 bascules
Périmètre
29 tables · 8 modules · 4 rôles
Rôle
Développeur full-stack
Pile
Angular · TypeScript · .NET · C# · SQL Server
Accès
Logiciel d'entreprise, non public
Saliou Sow Saliou Sow Directeur général · Jant Tech Jant Tech

« Souleymane a rejoint JANT TECH en 2022 et a travaillé trois ans sur nos plateformes clientes.

Sur la plateforme de gestion des opérations de la Nouvelle Minoterie du Sénégal, il a livré l’intégralité du périmètre défini avec le client — de l’approvisionnement en blé jusqu’à la livraison de la farine. Il a modélisé le suivi de production par équipe, une contrainte que peu de développeurs prennent au sérieux : dans une usine qui tourne vingt-quatre heures, un relevé saisi la nuit doit tomber dans le rapport du bon poste. »

Développement Modélisation Déploiement
Profil
Espace d'administration de la plateforme : la liste des utilisateurs d'une entreprise et le privilège attaché à chacun, sur poste et sur téléphone.
Secteur
Distribution de carburants
Échelle
~30 stations-services
Périmètre
5 modules · 9 rôles
Rôle
Analyste fonctionnel, puis développeur
Pile
Angular · TypeScript · .NET · C# · SQL Server
Accès
Logiciel d'entreprise, non public
Mohamed Amar Mohamed Amar Lead développeur · Jant Tech Jant Tech

« J’ai encadré techniquement Souleymane sur la plateforme comptable de notre client distributeur de carburants, une trentaine de stations-services.

Ce qui m’a marqué d’abord, c’est qu’il a commencé par le métier : avant d’écrire une ligne, il a conduit le recueil du besoin auprès du service comptable et rédigé les spécifications fonctionnelles — cinq modules et une matrice de droits couvrant neuf rôles, du directeur général aux agents comptables.

Il a ensuite développé ce qu’il avait spécifié. Les deux règles les plus délicates du dossier sont passées dans le système plutôt que de rester à la charge des comptables : la conversion entre les référentiels de mesure de la douane et du stockeur, et le rapprochement de chaque pièce avec la structure de prix en vigueur à sa date — une structure révisée toutes les quatre semaines par arrêté.

Il ne sépare pas ces deux moments : il spécifie en sachant qu’il devra exécuter, et il développe en sachant pourquoi la règle existe. C’est ce qui manque le plus souvent chez un développeur de son ancienneté. »

Analyse fonctionnelle Spécifications Développement
Profil
En production

Sept applications en production

Quatre s'essaient sans compte,
sans adresse courriel

Des produits en service, pas une galerie. Chacune tourne sur un serveur que j'administre, avec son domaine, son certificat et ses sauvegardes nocturnes. L'adresse est le seul bouton qui compte.

profmatch.soultaka.comProfMatch : les propositions d'affectation classees par score, avec leur rang et les actions de validation.
01 / 07Démo sans compte

ProfMatch

Affectation des professeurs aux cours. Les CV sont analysés automatiquement, les affectations proposées selon quatre critères pondérés, avec une justification lisible pour chaque recommandation.

Pour qui
Service des ressources humaines, Collège La Cité — livrée en trois semaines, à la tête de quatre développeurs
Pile
Next.js · FastAPI · PostgreSQL · Celery · Docker
safeottawa.soultaka.comSafeOttawa : un itinéraire piéton calculé entre deux intersections d'Ottawa, sa part de risque, sa distance et le nombre de zones traversées, sur fond de zones à risque.
02 / 07Lauréat InnovaCode 2026

SafeOttawa

Itinéraires les plus sûrs pour piétons et cyclistes. 94 406 collisions publiées par la Ville d'Ottawa deviennent 1 895 zones à risque, puis trois itinéraires classés.

Pour qui
Piétons et cyclistes d'Ottawa — données ouvertes de la Ville
Pile
Next.js · Python · PostgreSQL · Leaflet · OSRM
mediplan.soultaka.comMediPlan : le flux clinique du jour — chaque rendez-vous avec son heure, son médecin, son motif et son statut.
03 / 07Démo sans compte

MediPlan

Prise de rendez-vous pour cliniques. La réception et les patients réservent les mêmes créneaux sans jamais se marcher dessus, et un créneau annulé se rouvre au lieu de rester bloqué.

Pour qui
Cliniques médicales — projet intégrateur, équipe de trois
Pile
NestJS · Angular · PostgreSQL · TypeORM · Docker
techmaint.soultaka.comTechMaint : le tableau de bord d'une organisation de démonstration — interventions par statut, répartition et dernières interventions.
04 / 07Démo sans compte

TechMaint

Gestion des interventions terrain en mode SaaS : plusieurs entreprises sur la même plateforme, chacune ne voyant que ses propres données — y compris sur les canaux temps réel.

Pour qui
Entreprises de maintenance et leurs techniciens
Pile
.NET Core · Entity Framework · Angular · SignalR · PostgreSQL
devis-btp.soultaka.comDevis BTP : le tableau de bord de l'espace de démonstration — trois devis avec leur statut et leur montant.
05 / 07Démo sans compte

Devis BTP

Un artisan décrit ses travaux à voix haute ; l'application en fait un devis structuré, puis un PDF — avec les bonnes unités et les bons taux de TVA.

Pour qui
Artisans et petites entreprises du bâtiment
Pile
Angular · FastAPI · PostgreSQL · WeasyPrint · WebSocket
growth-engine.soultaka.comGrowth Engine : la première étape de l'installation — la définition du client idéal, sur laquelle les générations sont calibrées.
06 / 07

Growth Engine

Transforme un échange client en publications : génération, validation, publication. Le fournisseur d'IA se remplace sans réécrire l'application.

Pour qui
Indépendants et petites équipes qui publient régulièrement
Pile
Next.js · FastAPI · PostgreSQL · Celery/Redis
zengadget.soultaka.comZenGadget : le catalogue de la boutique, avec ses fiches produit et leurs variantes.
07 / 07

ZenGadget

Boutique en ligne bilingue, installable sur téléphone : catalogue, panier, commande.

Pour qui
Vente d'accessoires en ligne
Pile
Next.js · React · TypeScript · Tailwind · sans serveur ni base
←  Applications 01 / 07
Étude de cas · Application en production

ProfMatch

Un service des ressources humaines reçoit des CV en PDF et doit affecter des professeurs à des cours. L'application lit les CV, propose les affectations selon quatre critères pondérés, et porte une justification lisible sur chaque recommandation.

Pour qui
Service des ressources humaines, Collège La Cité
Délai
3 semaines
Équipe
4 développeurs, dirigés
Pile
Next.js · React · FastAPI · PostgreSQL · Celery · Redis · Docker
Ouvrir ProfMatch ↗ Sans compte · effacé au bout d'une heure
ProfMatch : vingt et une propositions d'affectation pour sept cours, chaque candidat avec son rang et son score.
Vingt et une propositions pour sept cours, chaque candidat avec son rang et son score. Rien n'est affecté tant qu'une personne n'a pas validé : l'application propose, le service RH décide.
ProfMatch : le périmètre d'une génération et les quatre pondérations W1 à W4.
Ce qui décide du score : quatre critères pondérés — compétences 40 %, expérience 30 %, historique 20 %, sémantique 10 % — dont la somme est contrainte à 1. Les poids sont fixés par l'administration, pas par le calcul.
ProfMatch : l'espace du professeur, avec la zone de dépôt du CV en PDF ou DOCX.
Le professeur dépose un PDF. La réponse est immédiate ; l'extraction, elle, part dans une file de tâches et prend vingt-trois secondes.
ProfMatch : le tableau de bord du service des ressources humaines.
Le flux est nommé dans l'ordre où il se pratique : choisir une session, sélectionner les programmes, ajuster les pondérations, générer, puis valider.
01Le besoin

Le tri se fait à la main : quelqu'un lit chaque CV, en retient des compétences, les rapproche des cours à pourvoir. C'est long, ce n'est pas reproductible, et personne ne peut expliquer six mois plus tard pourquoi telle personne a obtenu tel cours.

La commande vient du service des ressources humaines du Collège La Cité. Trois semaines, quatre développeurs. J'ai posé le cadre le premier jour — commits conventionnels, branches protégées, revues obligatoires — parce qu'à quatre sur trois semaines, ce qui n'est pas posé au début ne se pose plus.

02Ce que j'ai décidé

Le traitement long part dans une file de tâches.

Écarté
Attendre l'extraction dans le fil de la requête.
Pourquoi
L'extraction d'un CV par le modèle prend vingt-trois secondes. Dans le fil de la requête, c'est une application qui a l'air plantée : l'utilisateur recharge, et le traitement repart une seconde fois.

La justification est rédigée à la consultation, pas à la génération.

Écarté
Rédiger les trente justifications pendant la génération.
Pourquoi
Personne ne lit trente explications. L'enrichissement paresseux garde la génération à trois dixièmes de seconde et ne fait travailler le modèle que sur ce qu'on ouvre vraiment.

Les routes sont montées sans slash final.

Écarté
Laisser la redirection en place et rattraper l'en-tête côté client.
Pourquoi
Un navigateur retire l'en-tête d'autorisation quand une redirection change d'origine — et l'enchaînement hébergeur puis API en changeait. Résultat : 401 sur toutes les listes en production, 200 en appelant l'API directement. Deux chemins ont échappé à ma recherche manuelle ; c'est l'intégration continue qui les a trouvés.
03Mise en production

Le front est servi par Vercel sous profmatch.soultaka.com, l'API tourne en conteneurs sur un serveur que j'administre, derrière son propre nom et son certificat. Migrations de schéma versionnées, file de tâches et cache séparés du service web, intégration continue sur chaque poussée.

La démonstration publique n'est pas une copie d'écran : chaque visiteur obtient son propre espace, alimenté, effacé au bout d'une heure, et limité à quelques espaces par visiteur — les données de l'établissement, elles, restent en lecture.

Dépôt d'un CV
201, en 0,28 s
Extraction par le modèle
23,2 s en tâche de fond → 21 compétences, 3 expériences, 2 formations
Génération des affectations
30 en 0,31 s
Justification narrative
enrichie à la consultation, 12,1 s
Les sept chemins autrefois cassés
200, zéro redirection, 0,25 à 0,52 s
Cloisonnement des rôles
passe de 401 à 403 — l'autorisation arrive enfin
Tests
448, couverture 83,76 %, intégration continue verte
04Ce que je referais autrement

Le modèle rate la section « Profil » des CV alors qu'elle est bien présente — et ce champ alimente le critère sémantique, qui est donc calculé sans lui. Une perte de qualité silencieuse, la pire espèce.

Les routeurs de gestion courante sont peu couverts par les tests, malgré les 83 % globaux : la couverture dit la moyenne, pas où sont les trous.

Et l'historique du dépôt me crédite de la quasi-totalité des commits alors que nous étions quatre : j'intégrais le travail de l'équipe, et ça ne se lit pas dans les statistiques.

←  Applications 02 / 07
Étude de cas · Application en production · Lauréat InnovaCode 2026

SafeOttawa

Les outils de navigation optimisent le temps ou la distance. Aucun ne dit à un piéton que l'intersection suivante concentre trois fois plus de collisions que la précédente. SafeOttawa transforme 94 406 collisions publiées par la Ville en itinéraires classés par risque.

Pour qui
Piétons et cyclistes d'Ottawa
Données
94 406 collisions, données ouvertes de la Ville
Distinction
Lauréat InnovaCode 2026
Pile
Next.js · TypeScript · PostgreSQL · Leaflet · OSRM
Ouvrir SafeOttawa ↗ Ouvert à tous · aucun compte
SafeOttawa : un itinéraire piéton calculé entre deux intersections d'Ottawa.
Deux itinéraires classés entre King Edward et Bank : le recommandé à 13 % de risque, 3,0 km, 68 zones traversées ; l'alternative à 14 % pour un kilomètre de plus. Les corridors rouges sont les zones que les collisions publiées font ressortir.
SafeOttawa : le même trajet demandé avec le profil prudent.
Le même trajet, demandé en profil prudent. La tolérance au risque n'est pas un affichage : elle change le tracé rendu.
SafeOttawa : le formulaire de signalement et les signalements déjà déposés sur la carte.
Ce que la donnée ouverte ne dit pas, les gens le disent : signalement par clic sur la carte, type, description, et les signalements déjà déposés.
01Le besoin

Un piéton et un cycliste ne cherchent pas le trajet le plus court, mais celui dont ils reviendront. La Ville d'Ottawa publie ses collisions ; personne ne les met entre les mains de qui traverse.

94 406 collisions deviennent 1 895 zones à risque, et ces zones deviennent un coût que le calcul d'itinéraire additionne au kilomètre.

02Ce que j'ai décidé

Les signalements passent en base, avec validation stricte.

Écarté
L'écriture sur le disque de la machine, comme en développement.
Pourquoi
L'hébergement du front est en lecture seule : ce qui marchait sur mon poste ne pouvait pas marcher en ligne. Le défaut ne se voyait qu'une fois déployé.

L'appel au calculateur d'itinéraires passe en HTTPS.

Écarté
Laisser l'appel en clair, comme il l'était.
Pourquoi
Une page servie en HTTPS n'a pas le droit d'appeler une ressource en clair : le navigateur bloque, sans rien afficher. Le contrat rendu au client n'a pas changé — la carte n'a pas bougé.
03Mise en production

Front servi par Vercel sous safeottawa.soultaka.com, certificat automatique, calcul d'itinéraire par un moteur OSRM et fond de carte OpenStreetMap.

La chaîne a été rejouée en ligne, y compris un signalement rejeté avec sa raison : une validation qui n'a jamais refusé quoi que ce soit n'est pas une validation.

Collisions traitées
94 406
Zones de risque produites
1 895
Itinéraires rendus
classés par profil — prudent, normal, actif
Itinéraire mesuré ci-dessus
3,0 km · 13 % de risque · 68 zones
Signalement invalide
refusé, avec sa raison
04Ce que je referais autrement

Ni tests ni analyse statique sur ce projet. C'est un prototype de fin de semaine qui a survécu, et ça se voit : il a gagné un concours, il n'a pas de filet.

Un prix ne rend pas un dépôt propre. Si SafeOttawa devait servir tous les jours, la première semaine passerait à écrire ce qui manque.

←  Applications 03 / 07
Étude de cas · Application en production

MediPlan

Une clinique coordonne ses rendez-vous entre le téléphone, un agenda papier et un tableur. La réception détient le seul agenda qui fait foi. Deux personnes peuvent vendre la même place en même temps.

Pour qui
Cliniques de petite et moyenne taille
Équipe
3 — projet intégrateur
Période
Printemps 2026
Pile
NestJS · Angular · PostgreSQL · TypeORM · Docker
Ouvrir MediPlan ↗ Sans compte · effacé au bout d'une heure
MediPlan : le flux clinique du jour, chaque rendez-vous avec son statut.
Le flux du jour : chaque rendez-vous avec son heure, son médecin, son motif et son statut — réservé, arrivé, en consultation, terminé. C'est l'écran que la réception garde ouvert.
MediPlan : le tableau de bord de l'administrateur de clinique.
Le tableau de bord d'un administrateur de clinique. Le périmètre de clinique est appliqué par le serveur, pas par l'affichage : l'identité vient du jeton.
MediPlan : les statistiques de la clinique — volume, absences, occupation.
Volume, absences et taux d'occupation par médecin. Le créneau libéré par une annulation redevient réservable — c'est tout l'objet de la décision technique ci-dessous.
01Le besoin

Le médecin ne voit pas sa journée sans la demander. Le patient ne peut rien réserver lui-même. Et une annulation se perd en route : le créneau libéré n'est presque jamais réutilisé.

Projet intégrateur, équipe de trois. J'ai porté le socle technique et intégré les branches des deux autres — sur un projet d'équipe, l'intégration est souvent la part que personne ne veut prendre.

02Ce que j'ai décidé

Un index unique partiel, qui exclut les rendez-vous annulés.

Écarté
Une contrainte d'unicité simple sur le créneau.
Pourquoi
La contrainte simple crée un problème pire que celui qu'elle règle : un rendez-vous annulé occupe toujours la ligne, donc le créneau reste bloqué pour toujours et l'annulation devient inutilisable. Le prédicat partiel est tout l'intérêt.

La réception et le patient empruntent la même transaction, le même verrou, le même index.

Écarté
Deux chemins de réservation, un par canal.
Pourquoi
La garantie ne doit pas dépendre du canal. Ajouter un troisième canal demain ne rouvre pas le trou.

Le périmètre de clinique est appliqué par le serveur.

Écarté
Filtrer à l'affichage, en passant l'identifiant dans la requête.
Pourquoi
L'identité vient du jeton ; le corps de la requête n'expose aucun identifiant de patient. Un patient ne peut donc pas réserver au nom d'un autre, même en fabriquant la requête à la main.
03Mise en production

Front sous mediplan.soultaka.com, API en conteneurs sur un serveur que j'administre, migrations de schéma versionnées, intégration continue verte.

La démonstration donne à chaque visiteur sa propre clinique, alimentée, effacée au bout d'une heure, avec les trois rôles — administration, médecin, patient — sans se reconnecter.

Trois requêtes simultanées, même créneau
1 × 201, 2 × 409
Annulation, puis nouvelle réservation
le créneau redevient réservable
Patient appelant les statistiques
403
Médecin consultant le rendez-vous d'un autre
404 — pas de fuite d'existence
Export CSV
200, 187 lignes, accents intacts
Tests
205 — intégration continue verte
Sonde de disponibilité
200 ; 503 quand la base tombe
04Ce que je referais autrement

Le jeton vit dans le stockage local du navigateur, sans jeton de rafraîchissement ni liste de révocation : un compte désactivé garde l'accès jusqu'à l'expiration, au plus une heure.

Huit erreurs d'accessibilité subsistent sur des éléments cliquables non atteignables au clavier. Et la police d'icônes pèse 3,9 Mo à elle seule — le paquet initial dépasse le budget que je m'étais fixé.

←  Applications 04 / 07
Étude de cas · Application en production

TechMaint

Plusieurs entreprises de maintenance utilisent le même logiciel sans jamais se voir. Le cloisonnement tenait en HTTP et tombait dans le canal temps réel — et c'est le genre de défaut qu'aucun écran ne montre.

Pour qui
Entreprises de maintenance, plusieurs sur le même logiciel
Type
Projet personnel
Année
2026
Pile
.NET Core · Entity Framework Core · Angular · SignalR · PostgreSQL
Ouvrir TechMaint ↗ Sans compte · votre propre organisation, effacée au bout d'une heure
TechMaint : le tableau de bord d'une organisation, interventions par statut.
Une organisation de démonstration, créée pour vous : quatre clients, dix interventions, deux techniciens. Aucune autre organisation n'existe, de votre point de vue.
TechMaint : la carte des interventions et des techniciens.
Interventions et techniciens sur la carte, en temps réel. Le suivi de position est une simulation — il n'y a pas de source GPS ; le canal temps réel, lui, transporte de vraies diffusions.
TechMaint : le planning des interventions.
Le planning : qui est chez quel client, sur quel équipement, et où en est le travail.
01Le besoin

Une entreprise de maintenance suit ses interventions au téléphone et sur papier. Le logiciel doit servir plusieurs entreprises à la fois — et aucune ne doit jamais apercevoir les données d'une autre.

C'est un projet personnel, donc le sujet était choisi : je voulais l'isolation multi-locataire, parce que c'est là que les erreurs coûtent le plus cher et se voient le moins.

02Ce que j'ai décidé

Le filtre d'isolation passe en fermé par défaut.

Écarté
Le laisser ouvert par défaut, comme il l'était.
Pourquoi
Sans organisation identifiée, il laissait tout passer. En HTTP ce n'était pas visible : un intergiciel renseignait l'organisation avant chaque requête. Un filtre ouvert par défaut trahit exactement au moment où il devrait protéger.

Un filtre dédié aux invocations temps réel, appliqué à chaque appel.

Écarté
Se fier au contexte établi à la négociation initiale.
Pourquoi
Chaque invocation obtient un contexte de dépendances neuf, où l'organisation n'est jamais renseignée : n'importe quel utilisateur authentifié pouvait lire le nom et la position d'un technicien d'une autre entreprise.

C'est l'abonnement lui-même qui est refusé, pas seulement la lecture.

Écarté
Refuser la lecture et laisser l'abonnement.
Pourquoi
L'abonnement se faisait avant la lecture et lui aurait survécu : l'attaquant aurait continué à recevoir les diffusions suivantes.
03Mise en production

Front sous techmaint.soultaka.com, API en conteneurs sur le serveur que j'administre, canal temps réel authentifié.

La démonstration est la preuve de l'architecture : le bac à sable du visiteur n'est pas un dispositif ajouté, c'est le filtre du produit qui le rend possible. Deux bacs simultanés n'ont aucun identifiant commun.

Lecture d'une donnée d'une autre organisation
404, liste vide
Écriture sur un technicien d'une autre organisation
404, position intacte
Technicien tentant quatre actions d'administration
403 × 4
Le même technicien sur ses propres lectures
200
Origine tierce appelant l'API
aucun en-tête d'autorisation renvoyé
Suppression d'un client encore référencé
409 avec identifiant de trace
Négociation du canal temps réel
200 avec jeton, 401 sans
04Ce que je referais autrement

Le suivi de position des techniciens est une simulation pilotée depuis le navigateur : il n'y a aucune source GPS réelle. Le canal temps réel, lui, fonctionne et transporte de vraies diffusions ; c'est la donnée qui est simulée.

Le géocodage est hors service depuis que la clé de l'API cartographique a expiré. Il n'y a ni limitation de débit ni jeton de rafraîchissement, la logique métier vit encore dans les contrôleurs, et aucune liste n'est paginée.

←  Applications 05 / 07
Étude de cas · Application en production

Devis BTP

Un artisan du bâtiment rédige ses devis à la main ou dans un tableur : chaque ligne, chaque unité, chaque taux. C'est long, et l'erreur d'arrondi se paie chez le client. Ici, il décrit les travaux à voix haute et relit un devis structuré.

Pour qui
Artisans du bâtiment
Type
Projet personnel
Sortie
Devis structuré, puis PDF
Pile
Angular · FastAPI · PostgreSQL · WeasyPrint · WebSocket
Ouvrir Devis BTP ↗ Sans compte · une entreprise fictive et trois devis vous attendent
Devis BTP : le tableau de bord de la démonstration, trois devis avec statut et montant.
Trois devis d'exemple, avec leur statut — accepté, brouillon, envoyé — et leur montant. Le compteur d'essais de l'assistant est affiché en haut : cinq, et une dictée déjà analysée n'en consomme aucun.
Devis BTP : l'écran de création, dictée des travaux à gauche, aperçu du devis à droite.
À gauche, la description des travaux — dictée ou saisie. À droite, l'aperçu du devis qui se remplit : lignes, unités, quantités, taux, totaux. Puis le PDF.
01Le besoin

Le devis est le premier document que le client voit d'un artisan. Il est écrit le soir, après la journée de chantier, et c'est là que les erreurs entrent.

L'application prend la parole comme elle vient — une description parlée — et rend une structure : lignes, unités, quantités, taux, totaux.

02Ce que j'ai décidé

L'audio part encodé dans l'appel de génération.

Écarté
Un service de transcription séparé.
Pourquoi
Le fournisseur retenu n'en expose pas. L'audio devait voyager autrement, sans ajouter une seconde dépendance pour une seule fonction.

Une transcription tronquée lève une erreur explicite.

Écarté
La traiter comme une transcription complète.
Pourquoi
Le plafond de jetons inclut la réflexion du modèle : calibré pour un modèle sans raisonnement, il renvoyait du JSON tronqué. Des lignes de devis fausses valent moins qu'une erreur affichée.

La sortie du modèle est bornée par le code, pas par la consigne.

Écarté
Faire confiance au format demandé dans l'invite.
Pourquoi
Quantités strictement positives, taux ramenés à ceux qui existent, unités contraintes. Un modèle qui invente un taux de TVA n'est pas un cas rare, c'est un cas à prévoir.
03Mise en production

Front sous devis-btp.soultaka.com, API sur le serveur que j'administre, rendu PDF côté serveur.

La chaîne complète a été rejouée en ligne : inscription, devis, PDF.

Totaux
1 322,00 HT · 132,20 de TVA · 1 454,20 TTC — exacts au centime
PDF produit
13,9 Ko, douze contrôles de contenu
Transcription tronquée
erreur explicite, aucune ligne inventée
Chaîne rejouée en ligne
inscription → devis → PDF
04Ce que je referais autrement

Le canal temps réel fonctionne et il est authentifié, mais aucun écran ne l'utilise : j'ai construit une capacité avant son usage.

Le schéma de base n'est pas versionné par des migrations — ce qui va tant que je suis seul dessus, et plus du tout dès qu'on est deux.

←  Applications 06 / 07
Étude de cas · Application en production

Growth Engine

Transformer un appel client enregistré en publications, sans réécrire ce que le client a dit. Le fournisseur d'IA a changé en cours de route — et l'application n'a pas eu à changer.

Pour qui
Indépendants et petites équipes B2B
Type
Projet personnel
Traitements
Asynchrones, file de tâches
Pile
Next.js · FastAPI · PostgreSQL · Celery · Redis
Ouvrir Growth Engine ↗ Compte requis · pas de démonstration publique
Growth Engine : la bibliothèque de gabarits de publication.
Les gabarits de publication, classés par intention. Le style est un objet du système, pas une consigne cachée dans une invite.
Growth Engine : la définition du client idéal, en quatre étapes.
L'installation en quatre étapes commence par le client visé : toutes les générations sont calibrées dessus, plutôt que sur une consigne réécrite à chaque fois.
Growth Engine : la saisie d'une conversation client pour en extraire les objections.
Les objections sont extraites d'une vraie conversation et citées telles quelles, jamais reformulées : c'est la règle du produit, et elle est écrite sur l'écran.
Growth Engine : la liste des publications, vide sur un compte neuf.
L'atelier de publications, sur un compte neuf : brouillon, prêt, planifié, publié. Cette capture est vide, et elle le reste — je ne remplis pas un écran pour la photo.
01Le besoin

Un indépendant qui vend ses services parle mieux qu'il n'écrit. L'appel client contient déjà les mots justes : les objections, les angles, le ton.

L'application ingère la conversation, en extrait ce qui a été dit, et propose des publications — sans jamais présenter comme une citation ce qui n'en est pas une.

02Ce que j'ai décidé

Toute la surface d'appel au modèle tient dans une seule fonction.

Écarté
Appeler le fournisseur depuis chaque service qui en a besoin.
Pourquoi
Le fournisseur a changé en cours de route. La bascule s'est faite sans toucher aux appelants — c'est la seule raison pour laquelle elle n'a pas coûté une réécriture.

Une marge de jetons est ajoutée dans la couche d'appel.

Écarté
Garder le plafond calibré pour l'ancien modèle.
Pourquoi
Le nouveau modèle réfléchit, et sa réflexion consomme le budget de sortie : sans marge, la réponse utile était tronquée.

Deux gardes : sortie vide et réponse tronquée lèvent des erreurs explicites.

Écarté
Laisser passer et corriger à l'affichage.
Pourquoi
Une publication à moitié générée ressemble à une publication. C'est exactement ce qu'il ne faut pas laisser passer.
03Mise en production

Front sous growth-engine.soultaka.com, API et file de tâches sur le serveur que j'administre, authentification par jeton vérifié côté serveur.

La chaîne complète a été rejouée en ligne : inscription, connexion, huit gabarits chargés, session tenue par cookie.

Trois variations générées
21,4 s, avec le bon type de publication
Chaîne rejouée en ligne
inscription → connexion → huit gabarits → session
Sortie vide ou tronquée
erreur explicite, rien n'est publié
Changement de fournisseur
aucun appelant modifié
04Ce que je referais autrement

La transcription audio n'est pas disponible : la dépendance pèse deux gigaoctets et je ne l'ai pas embarquée. C'est un arbitrage, pas un oubli, et il est écrit dans le dépôt.

Il n'y a pas d'ordonnanceur : les publications planifiées attendent qu'on les déclenche. Une capacité annoncée par l'écran doit exister derrière, ou disparaître de l'écran.

←  Applications 07 / 07
Étude de cas · Application en production

ZenGadget

Une boutique complète — seize pages, deux langues, un panier qui survit au rafraîchissement — sans serveur ni base de données. La contrainte était l'énoncé du cours ; elle est devenue l'exercice intéressant.

Pour qui
Travail de cours, programmation web avancée
Équipe
3
Particularité
Aucun serveur, aucune base
Pile
Next.js · React · TypeScript · Tailwind · react-intl
Ouvrir ZenGadget ↗ Ouvert à tous · aucun compte
ZenGadget : le catalogue de la boutique.
Seize pages, toutes pré-rendues. Les données produits sont statiques, écrites en TypeScript — donc vérifiées à la compilation plutôt qu'à l'exécution.
ZenGadget : une fiche produit avec ses variantes.
Une fiche produit et ses variantes. Le contenu est bilingue et le changement de langue n'appelle rien : tout est déjà dans la page.
ZenGadget : le panier, avec le total et la mention « simulation seulement ».
Le panier survit au rafraîchissement, sans serveur : l'état vit dans le navigateur. Et la page dit ce qu'elle est — « simulation seulement, aucun paiement ne sera effectué ».
01Le besoin

Travail de cours en programmation web avancée, en équipe de trois : une boutique complète, sans backend ni base de données.

Tout l'état vit donc dans le navigateur. Le panier doit survivre au rafraîchissement, le thème et la langue aussi, sans provoquer d'incohérence au premier rendu — le défaut classique d'une page pré-rendue qui découvre les préférences après coup.

02Ce que j'ai décidé

Les données produits sont statiques, en TypeScript.

Écarté
Un fichier JSON chargé à l'exécution.
Pourquoi
Le typage attrape à la compilation ce qu'un JSON laisse découvrir en production, et les seize pages peuvent être pré-rendues.

L'état vit en contexte React, les préférences en stockage local.

Écarté
Un état global chargé au démarrage.
Pourquoi
Sans serveur, il n'y a rien d'autre. Ce qui compte est l'ordre : lire les préférences avant le premier rendu visible, sinon la page clignote de la mauvaise langue.
03Mise en production

Servi par Vercel sous zengadget.soultaka.com. Aucune fonction serveur, aucune base : le site entier est un ensemble de pages pré-rendues, installable comme application.

Pages
16, toutes statiques
Fonctions serveur
aucune
Langues
deux, interface complète
Tests
25, de structure
04Ce que je referais autrement

Les tests vérifient la présence des choses, pas leur comportement : ils cassent sur un renommage et laissent passer un vrai défaut. C'est le pire rapport entre le coût et la garantie.

Et le contenu produit n'est pas traduit — seule l'interface l'est. Une boutique bilingue dont les fiches ne le sont pas est bilingue à moitié.

Les objections

Les questions qu'on me pose

Répondues ici pour
n'avoir pas à être posées
01Quel poste visez-vous, et où ?+

Développeur full-stack, sur des applications métier ou du SaaS. Disponible à Montréal, Ottawa et Toronto, et à distance ailleurs.

02Êtes-vous autorisé à travailler au Canada ?+

Oui — permis de travail valide. Aucune démarche à engager de votre côté.

03Sur quelle pile êtes-vous le meilleur ?+

Angular et .NET Core — c'est là que j'ai le plus de kilomètres : trois ans en entreprise et les deux plateformes client. Ensuite React/Next.js et Python/FastAPI, sur lesquels j'ai livré cinq applications en production, et NestJS sur une sixième.

Mais la vraie réponse est ailleurs. Ce qui se transporte d'une pile à l'autre — le recueil du besoin, les spécifications, le modèle de données, le cloisonnement, les tests, la mise en production — ne dépend d'aucune d'entre elles. Les sept applications ne sont pas construites sur la même pile, et c'est délibéré : je m'insère dans un écosystème au lieu d'en exiger un.

Si votre pile est dans cette liste, je suis productif tout de suite. Si elle n'y est pas, ce que je sais faire ne s'y perd pas.

Front-end
Angular · TypeScript · RxJS · React · Next.js
Back-end
C# · .NET Core · Python · FastAPI · NestJS
Données
PostgreSQL · SQL Server · Celery · Redis
Exploitation
Docker · GitHub Actions · Vercel · Linux · Caddy
Analyse
Recueil du besoin · spécifications · UML · multi-locataire
04Ces projets sont-ils professionnels ou académiques ?+

Les deux, et je le dis parce que ça se vérifie. Trois ans chez un éditeur de logiciels, dont deux plateformes livrées à des clients nommés. ProfMatch était une commande du service des ressources humaines du Collège La Cité, livrée en trois semaines et présentée devant un comité — le résultat du concours n'est pas encore annoncé. MediPlan était un projet intégrateur encadré, SafeOttawa a remporté InnovaCode 2026, les trois autres sont personnels.

Tous sont en ligne, tous sont exploités, aucun n'est une maquette.

05Ces sept applications, vous les avez faites seul ?+

Cinq sur sept, oui — et je le dis avant qu'on me le demande, parce que c'est la bonne question. Les deux autres sont celles qui comptent pour un employeur : ProfMatch à la tête de quatre développeurs, MediPlan en équipe de trois. Avant cela, deux ans dans une équipe d'éditeur, sur du code que je n'avais pas écrit seul.

Les cinq projets solo ne prouvent pas le travail en équipe. Ils prouvent autre chose : que je mène une application jusqu'en production et que je l'y maintiens, sans que personne ne le fasse à ma place.

06Comment travaillez-vous en équipe ?+

En méthode agile : sprints, backlog tenu dans Jira, revues de code obligatoires avant fusion, branches protégées et commits conventionnels. Le cadre est posé le premier jour, pas au milieu — à quatre sur trois semaines, ce qui n'est pas posé au début ne se pose plus.

Sur ProfMatch j'ai dirigé quatre développeurs et fixé ces standards. Sur MediPlan, en équipe de trois, j'ai porté le socle technique et intégré les branches des deux autres. Chez Jant Tech, Git Flow et revue avant fusion. Sur un projet d'équipe, l'intégration est souvent la part que personne ne veut prendre.

07Savez-vous travailler avec des utilisateurs qui ne sont pas informaticiens ?+

C'est par là que j'ai commencé. Sur la plateforme comptable du distributeur de carburants, mon premier rôle a été analyste fonctionnel : comprendre le métier avec le service comptable, puis rédiger les spécifications fonctionnelles avant d'écrire une ligne.

Le chef comptable a détaillé par écrit ses tâches quotidiennes, hebdomadaires, mensuelles et annuelles ; c'est de là que sortent les règles du système, pas d'une hypothèse. Trois ans plus tard, même chemin avec le service des ressources humaines du Collège La Cité.

08Vos réalisations sont-elles vérifiables ?+

Sept applications tournent à des adresses publiques, ouvrables tout de suite ; quatre s'essaient sans compte et sans adresse courriel. Chaque étude de cas porte ses mesures et ses captures.

Les deux plateformes client sont des logiciels d'entreprise, non publics — j'en détaille le périmètre en entretien.

Contact

Vingt minutes suffisent pour savoir si mon profil correspond à votre besoin.

Un poste à pourvoir, une question sur une application, ou l'envie de vérifier une chose écrite plus haut : écrivez-moi.

Coordonnées
Courrieldiallosouleymanetaka@gmail.com LinkedInsouleymane-taka-diallo GitHubsoultaka19
RéponseSous 24 heures
DisponibleImmédiatement — temps plein, contrat ou pige
StatutPermis de travail ouvert : aucune démarche pour l'employeur
Sur placeMontréal · Ottawa · Toronto · à distance