Pourquoi j'investis 3 semaines pour gagner 6 mois (le secret des devs qui livrent 10x)
J'ai 8 bibliothèques personnelles que je publie en privé sur npm. Aucune n'a été 'planifiée'. Chacune est née d'un projet client où j'ai dit 'tiens, c'est la troisième fois que j'écris ce code'. Voici la stratégie d'extraction qui a transformé ma productivité — et les pièges qui m'ont coûté du temps avant que je la comprenne.
Cet article décortique le projetPortfolio EngineeringLa règle des 3
Voici la règle qui définit ma productivité depuis 18 mois :
À la première occurrence, j'écris le code dans le projet. À la deuxième occurrence, je le copie-colle. À la troisième occurrence, je l'extrais.
C'est ça. Une règle. Trois mots. C'est tout ce qui sépare un dev qui livre 10× plus que ses pairs d'un dev qui ne le fait pas.
Et pourtant, c'est exactement ce que la plupart des devs ne font jamais.
Mes 8 bibliothèques personnelles
Voici mon monorepo portfolio-libs, publié en privé sur npm. Chaque
bibliothèque a une origine précise dans un projet client réel :
@portfolio/crdt-engine ← extrait de MyRoadTrip (3× réécrit avant l'extraction)
@portfolio/offline-core ← extrait de MyRoadTrip
@portfolio/map-engine ← extrait de MyRoadTrip (clustering 50K points)
@portfolio/chart-kit ← extrait de Racine + SaleCast (graphes SVG < 2 Ko)
@portfolio/vue-kit ← extrait de 3 projets Vue 3 différents
@portfolio/backend-kit ← extrait de PromptVault (helpers Fastify)
@portfolio/mock-utils ← extrait de tous mes projets (faker maison)
@portfolio/build-config ← config Vite + TS + ESLint partagée
Chacune fait entre 400 et 1 500 lignes. Aucune n'est un framework. Aucune ne tente d'être "exhaustive". Chacune fait une chose précise, la plus utile, et se fait oublier.
C'est cette dernière propriété qui compte : se faire oublier. Une bonne lib est invisible à l'usage. Si je dois lire la doc à chaque fois, c'est qu'elle est trop complexe.
Ce que ça change en pratique
Sans portfolio-libs, chaque nouveau projet me coûte :
Semaine 1-2 : setup Vite, TypeScript, ESLint, fonts, theming, layout
Semaine 3 : auth (OAuth/JWT/session)
Semaine 4-5 : data layer (forms, validation, error handling)
Semaine 6-7 : la fonctionnalité métier (le "vrai" travail)
5 semaines avant d'écrire la première ligne du produit.
Avec portfolio-libs, chaque nouveau projet me coûte :
Jour 1 : pnpm install @portfolio/build-config, configure tsconfig
Jour 2 : pnpm install @portfolio/vue-kit, layout en place
Jour 3-4 : pnpm install @portfolio/offline-core si offline-first nécessaire
Jour 5-7 : la fonctionnalité métier
7 jours pour atteindre le code métier. Multiplié par 9 projets en 18 mois, ça fait ~12 mois économisés.
Comment je décide quoi extraire
C'est le piège classique du dev qui découvre cette idée : il extrait trop tôt. Il prend un truc qu'il a écrit une fois et il le mette en lib "au cas où". 6 mois plus tard, il a 40 libs dont 35 ne servent à rien et bloquent l'évolution des 5 qui servent.
J'utilise 4 critères de validation avant d'extraire :
1. Le code a été utilisé 3 fois dans 3 projets différents
Pas "j'ai copié 3 fois dans 3 fichiers du même projet". Trois projets indépendants qui n'auraient pas dû se connaître.
Si le code n'a jamais existé que dans MyRoadTrip, il reste dans MyRoadTrip. Quand j'aurai besoin de la même chose dans SaleCast, je le réécrirai (rapidement, car je connais déjà la forme finale). Si je le réécris dans un troisième projet, là j'extrais.
2. La signature n'a pas changé depuis 2 itérations
C'est la garantie que je sais ce que c'est. Si après 3 implémentations j'ai toujours pas trouvé le bon nom de fonction ou le bon set d'arguments, c'est que je ne comprends pas encore la vraie abstraction. Extraire serait prématuré.
3. Le code fait UNE chose
Pas deux. Pas "deux choses liées". Une seule chose.
@portfolio/crdt-engine synchronise des documents Yjs avec un backend.
Il ne fait pas la persistance locale (c'est @portfolio/offline-core).
Il ne fait pas l'UI (c'est @portfolio/vue-kit).
Il ne fait pas le polling (c'est le user qui décide quand sync).
Une lib qui fait deux choses devient un mini-framework. Et les frameworks meurent dès qu'un projet a un besoin qui s'écarte.
4. Je peux faire un test de fumée en 5 minutes
C'est mon test de "est-ce que ça vaut le coup ?". J'écris dans un nouveau
projet un fichier main.ts qui utilise la lib comme si elle existait déjà :
import { CRDTEngine } from '@portfolio/crdt-engine';
const engine = new CRDTEngine({ strategy: 'field' });
engine.onMerge(change => syncToServer(change));
engine.bind(doc);
Si ce code est évident à lire sans connaître l'implémentation, c'est la bonne API. Si je dois inventer des paramètres bizarres ou des callbacks complexes, c'est que je n'ai pas compris la lib. Je n'extrais pas encore.
Les 3 pièges que j'ai dû éviter
Piège 1 — Versioner avec semver dès le jour 1
Tentation : "Je publie en 1.0.0, c'est sérieux."
Réalité : le mois suivant, je veux changer la signature de la fonction
principale. Je me retrouve à émettre un 2.0.0 breaking sur 1 utilisateur
(moi-même).
Solution : tout reste en 0.x.y pendant les 6 premiers mois. Le 0
m'autorise à tout casser. C'est une discipline mentale autant que technique.
Piège 2 — Vouloir publier en public sur npm tout de suite
Tentation : "Si j'extrais bien, autant le partager."
Réalité : publier en public ajoute :
- Documentation publique à maintenir
- Issues GitHub à gérer
- Tests sur des navigateurs/runtimes que je n'utilise pas
- Compatibilité backwards à respecter
Solution : npm publish --tag private dans un registre privé. Tant que je
n'ai pas 3 utilisateurs externes intéressés, je ne dépense pas un dollar
de mon temps en doc publique.
Sur mes 8 libs, une seule est publique (@poisson/engine). Les 7 autres
sont privées. Et c'est très bien.
Piège 3 — Refactorer "en silo"
Tentation : "Cette lib est moche, je vais la refactorer pendant mon temps mort."
Réalité : le refactor traîne 3 semaines parce que je n'ai pas de "vrai" projet pour valider que les changements n'ont rien cassé. Et quand je finis, j'ai oublié pourquoi je changeais ces choses.
Solution : je ne refactore jamais une lib hors d'un projet client. Quand un projet client a besoin d'une nouvelle feature de la lib, je refactor dans le projet client, je commit, puis je back-port la lib à partir du projet.
Le projet client paye pour le refactor. La lib en bénéficie. Personne n'est en silo.
L'effet long-terme
À l'année 2, mes libs sont plus matures que mes projets. À l'année 3, mes projets sont quasi-100 % composés de mes libs + ~20 % de code métier.
Cette inversion — la majorité de mon code n'est plus écrite, elle est réutilisée — est ce qui fait passer un dev de "j'écris du code" à "je résous des problèmes en orchestrant du code que j'ai déjà".
C'est la définition concrète du senior.
Pas l'expérience en années. Pas le diplôme. Pas le titre. Le ratio de code réutilisé / code nouveau sur un nouveau projet.
Le mien est passé de 0 % en 2022 à 65 % en 2026. C'est ça qui me permet de livrer 9 produits en 11 mois.
Stack & code
- Monorepo pnpm + Turbo dans
/Users/floriansola/Documents/PORTFOLIO/ - 8 portfolio-libs publiées en privé
- 12 portfolio-projects = des démos qui valident chaque lib
- Couverture de tests par lib : 89-97 %
- Build cache Turbo : 90 % de hit rate, 9× plus rapide qu'un build cold
@portfolio/build-config: config Vite + TS + ESLint partagée. Mes nouveaux projets démarrent avec 1 ligne dansvite.config.ts:
import { createViteConfig } from '@portfolio/build-config/vite';
export default createViteConfig({ port: 5180, name: 'my-app' });
C'est ça, vivre dans son propre framework personnel. C'est moins prestigieux que "je code en React". C'est largement plus puissant.
La leçon
Tu n'as pas besoin d'écrire ton propre framework. Tu n'as pas besoin de ré-inventer React, Vue, ou Vite.
Mais tu as besoin de ta propre couche au-dessus. La couche qui fait que ton premier jour sur un nouveau projet ne consiste pas à recoder ce que tu as déjà codé 14 fois.
Cette couche n'a pas de nom. Personne ne te l'enseigne. Aucun bootcamp ne la mentionne. Et pourtant chaque dev senior productif que j'ai rencontré a la sienne.
Demande-leur. Ils te montreront un repo privé qu'ils ne montrent jamais. C'est leur arme.
Construis la tienne.
Florian Sola
Lead Technique · Haute performance temps réel · 9 ans d'expérience