Étude de cas · Personnel
Générateur de CV lisible par les ATS, avec serveur MCP
Bibliothèque de CV bilingue rendue en PDF d’une page stricte, contrôlée pour les ATS, avec un serveur MCP dont les outils d’écriture ne créent que des propositions.
En bref
- Outil personnel pour adapter un CV d’une page et une lettre à chaque offre, en français ou en anglais, sans perdre de contenu ni laisser une IA inventer des faits.
- Monorepo TypeScript API Hono, interface React, rendu Typst avec contrôle automatique de lisibilité ATS, et serveur MCP de 21 outils dont les écritures ne sont que des propositions.
- Spécifié, conçu, relu et recetté par moi code écrit avec Claude Code. Il tourne en ligne derrière une connexion par clé d’accès et alimente ce portfolio.
En résumé
- Rôle
- Développeur unique
- Équipe
- Projet individuel
- Période
- Statut
- Utilisé pour mes propres candidatures
- Assistance IA
- importante Spécification, architecture, revue, tests et recette par moi code écrit avec Claude Code.
- Technologies
Contexte
Projet personnel, commencé en octobre 2026 pour mes propres candidatures d’emploi et de stage. Je voulais une source unique pour le contenu de mon CV en français et en anglais, et un moyen d’adapter un CV d’une page à chaque offre.
Problème
Adapter un CV à la main produit des copies qui divergent, des traductions qui vieillissent et des pages qui débordent. Demander à un assistant IA va plus vite, mais il peut reformuler des faits en affirmations fausses. Je voulais aussi savoir ce qu’un logiciel de recrutement (ATS) lit réellement dans le PDF.
Mon rôle, l’équipe et la part de l’IA
Projet solo. J’ai écrit le cahier des charges (environ 1 100 lignes) et les 20 décisions d’architecture, choisi l’architecture, relu le code et mené les tests et la recette. Le code a été écrit avec Claude Code à partir de ce cahier des charges.
Contraintes
- Aucune invention une IA peut suggérer, jamais décider chaque chiffre et chaque compétence doivent venir de la bibliothèque.
- Une page, strictement un export qui déborde est refusé, avec le dépassement chiffré en lignes.
- Bilingue un CV anglais ne peut pas être exporté tant qu’un champ affiché n’est pas traduit.
- Confidentialité les coordonnées et la photo ne sont jamais renvoyées à l’IA les vraies données n’entrent jamais dans le dépôt.
Solution et architecture
- Données une bibliothèque JSON de 10 collections (expériences, formations, projets, compétences…) à champs bilingues validés par Zod une traduction manquante vaut
null, jamais une chaîne vide. Presets et candidatures sont des sélections à trois états sur la bibliothèque. - Rendu des modèles Typst (ATS, visuel, lettre) produisent un PDF déterministe, ainsi qu’une version DOCX.
- Contrôle ATS le texte est réextrait du PDF avec deux extracteurs différents pour vérifier coordonnées, intertitres et dates une batterie de 72 cas couvre mises en page, langues et polices.
- Interfaces une API Hono, une interface React/Vite et un serveur MCP de 21 outils et 3 prompts guidés. Ses outils d’écriture ne créent que des propositions, que j’accepte ou rejette dans l’interface, et des garde-fous côté serveur rejettent les chiffres ou compétences absents de la source.
- Imports un export de données LinkedIn et des CV existants deviennent des propositions dédoublonnées les lettres sont versionnées, jamais écrasées.
- Instance en ligne connexion par clé d’accès (WebAuthn), en-têtes de sécurité et CSP stricts, service durci, et script de déploiement qui revient automatiquement à la version précédente si le contrôle de santé échoue.
Stack
TypeScript, Node.js, npm workspaces, Hono, React 19, Vite, Zustand, Zod, Typst, docx, pdf.js, SDK Model Context Protocol, WebAuthn, Vitest, ESLint, nginx, systemd.
Qualité et vérification
- Environ 410 cas Vitest unitaires, API, serveur MCP en mémoire et en stdio, et connexion par clé d’accès avec un authentificateur logiciel.
- La batterie de 72 cas de lisibilité ATS, et 8 scénarios de recette écrits, rejoués avant la mise en ligne.
- Un hook de pré-commit bloque les vraies données et les secrets les jeux de test utilisent des personnes fictives.
Résultats et statut
Je l’utilise pour mes propres candidatures, et les expériences, formations et compétences de ce portfolio sont exportées de sa bibliothèque. L’instance en ligne est privée.
Ce que je ferais autrement
- Ajouter une intégration continue qui lance les tests à chaque push, au lieu de compter sur les exécutions locales avant déploiement.
- Produire dès le départ des captures publiques à partir des personnes fictives, pour pouvoir montrer le projet sans exposer de vraies données.
- Séparer le README public des notes d’exploitation, pour pouvoir ouvrir le dépôt sans réécrire l’historique.
Liens
- Code source dépôt privé, à ouvrir après nettoyage.
- Captures d’écran à venir, réalisées avec des données fictives.