Project A
Plateforme de prospection B2B : signaux d'intention, enrichissement des coordonnées et séquences de contact générées par IA avec vérification des sources. Conçue, développée et mise en production en solo.

Le point de départ
Project A est un outil de prospection commerciale B2B que j'ai conçu, développé et mis en production seul. L'envie de départ : construire un vrai produit de bout en bout, pas une démo jetable, mais quelque chose qui tient debout, du positionnement jusqu'au déploiement.
Je me suis inspiré de Zeliq, un acteur du marché, et j'ai fait un pari assumé : plutôt que d'effleurer dix fonctionnalités, en pousser une seule à fond (la génération de messages par IA) et bâtir autour d'elle une colonne vertébrale crédible. Tout le reste du produit existe pour amener l'utilisateur, naturellement, jusqu'à cette pièce maîtresse.
Le problème
La journée d'un commercial (un « SDR ») se résume à trois gestes : trouver qui contacter, obtenir ses coordonnées, puis écrire un message qui donne envie de répondre. En pratique, il passe ses matinées à chercher et ses après-midis à rédiger des messages que personne n'ouvre. Les informations qui rendraient ces messages pertinents (un recrutement lancé, une levée de fonds, un post LinkedIn) sont éparpillées partout, et périmées dès qu'on les trouve.
Le produit, page par page
Voici comment un commercial utilise Project A, dans l'ordre.
L'idée qui relie tout : les signaux
On ne contacte pas quelqu'un au hasard : on le contacte parce qu'il se passe quelque chose chez lui. Une levée de fonds, un changement de poste, un recrutement, un post LinkedIn : ce sont des signaux d'intention. Ils servent à deux choses : filtrer la liste pour trouver qui contacter maintenant, et donner à l'IA une raison concrète d'écrire.
1. Trouver : la liste des prospects
Une base d'environ 150 prospects, filtrable par séniorité, secteur, taille d'entreprise, localisation et surtout par type de signal. Un détail que j'aime : les filtres vivent dans l'URL. On copie le lien d'une recherche filtrée, on le partage, et l'autre voit exactement le même résultat.

2. Enrichir : obtenir les coordonnées, sans boîte noire
Un nom ne suffit pas : il faut l'email et le téléphone. Un clic sur « Enrichir » interroge une cascade de fournisseurs de données, essayés un par un jusqu'au premier qui trouve. Ce qui compte, ce n'est pas seulement le résultat, c'est la transparence : l'app montre d'où vient la donnée (Datagma a raté, People Data Labs a trouvé), avec un score de confiance. Pas de boîte noire : l'utilisateur voit la donnée et sa provenance.
3. Générer : une séquence de messages, écrite par l'IA
C'est le cœur du produit. Un clic, et l'IA construit une séquence de contact complète : elle choisit le nombre d'étapes, les canaux (email, LinkedIn), les délais entre les messages, puis rédige chacun en direct, sous les yeux de l'utilisateur. Le texte s'écrit en streaming, comme sur ChatGPT.
4. Vérifier : la preuve, phrase par phrase
L'IA générative invente parfois des faits ; c'est un fait. Ma réponse produit n'est pas « faites-moi confiance », c'est « voici la preuve ». Une fois un message écrit, une seconde IA indépendante le relit et classe chaque phrase : sourcée (appuyée sur un signal réel, avec une note de bas de page), neutre (politesse, question), ou non vérifiée (signalée d'un drapeau). Un compteur affiche le ratio de phrases sourcées, et un bouton « Regénérer (grounded) » réécrit le message en interdisant les affirmations non soutenues. Survoler une phrase illumine le signal qui la justifie, et inversement.

Enfin, un tableau de bord (l'écran en tête de page) agrège tout : les KPIs, le taux de grounding vérifié, et un score d'engagement qui classe les prospects chaud / tiède / froid et recommande la prochaine action à mener.
Sous le capot
Pour les curieux, voici les choix techniques qui m'ont demandé le plus de réflexion, avec à chaque fois l'alternative que j'ai écartée.
Une architecture full-stack, pas de backend séparé
L'app repose sur TanStack Start, un framework full-stack : le même projet contient les pages React et le code serveur (l'API, l'accès à la base, les appels à l'IA). Le navigateur ne parle jamais directement à la base de données ni à l'API d'Anthropic : tout passe par le serveur de l'app, qui joue le rôle de garde-barrière. Un seul service tourne à part, et c'est un choix : le micro-service d'enrichissement.
Le micro-service NestJS : l'envie de tester le framework
J'avais envie de me frotter à NestJS sur un vrai bout de produit, un framework que je voulais explorer pour de bon, pas juste survoler dans un tutoriel. Restait à l'introduire intelligemment : plutôt que de bâtir le cœur du produit dessus, je lui ai confié une brique bornée et isolée, le waterfall d'enrichissement. La génération IA, la pièce maîtresse, reste sur ma stack principale (React, tRPC) ; NestJS prend un morceau autonome, où je peux expérimenter sans mettre le reste en jeu.
Ce découpage a du sens au-delà de l'exercice : c'est exactement le genre de composant qu'on isole en production. Sans état (aucune base, juste un prospect qui entre et un résultat qui sort), il pourrait scaler et se déployer indépendamment. Son hasard est même déterministe : le même prospect donne toujours le même résultat, ce qui rend le comportement reproductible et le service testable.
Alternative écartée : tout garder dans l'app, en une simple fonction. Plus court, mais je passais à côté de NestJS, et de l'occasion de raisonner sur de vraies frontières entre services.
La génération IA : trois passes, pas une
Un seul appel qui ferait tout le ferait mal. J'ai découpé le travail en trois étapes, chacune avec le bon modèle : planifier (l'IA décide la structure de la séquence, renvoyée en JSON strictement contraint), rédiger (le texte, en streaming), auditer (une IA différente, plus petite et moins chère, relit et note chaque phrase).
Le point clé, c'est le grounding : je ne donne au modèle rédacteur que les signaux réels comme source de faits, et je lui interdis d'en inventer d'autres. Moins il a de latitude, moins il hallucine. Et l'auditeur est un second modèle : demander au rédacteur de s'auto-noter serait un conflit d'intérêts ; un modèle qui n'a pas écrit le texte fait un vrai contre-contrôle.
Le streaming : SSE plutôt que WebSockets
Pendant la génération, le serveur parle et le navigateur écoute : un flux à sens unique. J'ai choisi les Server-Sent Events : du HTTP normal, sans serveur temps-réel à monter à côté de l'app, qui traverse les hébergeurs sans configuration et se reconnecte tout seul. Un WebSocket aurait ajouté une vraie pièce d'infrastructure pour une capacité bidirectionnelle que je n'utilise jamais ici. On le choisirait dès que le temps réel devient collaboratif, pas pour du streaming descendant.
Le design system : fait main
Aucune librairie de composants toute faite : tout est construit et documenté dans Storybook, à partir de design tokens décrits en OKLCH, un format de couleur qui exprime la luminosité telle que l'œil la perçoit. Concrètement, ça rend les contrastes cohérents entre teintes (l'accessibilité par construction) et le thème sombre presque gratuit : un simple décalage de luminosité, à teinte constante. C'est le genre de fondation qui donne au projet un air de produit fini plutôt que de prototype.
Ce que ce projet démontre
Un produit complet, livré par une seule personne : positionnement, design, front, back, base de données, intégration IA avec garde-fous, mise en production. Le genre de projet qui me plaît : prendre un sujet de bout en bout et le pousser jusqu'à quelque chose de soigné.