[{"data":1,"prerenderedAt":524},["ShallowReactive",2],{"article-/blog/streamtrackr-pro-mon-premier-projet-rentable":3},{"id":4,"title":5,"body":6,"date":506,"description":507,"extension":508,"image":45,"meta":509,"navigation":515,"path":516,"seo":517,"stem":518,"tags":519,"__hash__":523},"articles/blog/streamtrackr-pro-mon-premier-projet-rentable.md","StreamTrackr passe en Pro (et devient mon premier projet rentable)",{"type":7,"value":8,"toc":494},"minimark",[9,24,36,39,46,51,58,64,67,71,74,77,107,114,118,121,124,170,173,177,188,208,215,222,285,296,300,307,318,336,343,350,354,357,371,385,407,421,435,445,449,452,478,482,485,488],[10,11,12,13,18,19,23],"p",{},"Quand j'ai présenté ",[14,15,17],"a",{"href":16},"/projects/streamtrackr","StreamTrackr"," sur ce blog en 2024, je terminais par cette phrase : « ",[20,21,22],"em",{},"Pour l'instant, je pense avoir fait le tour des fonctionnalités principales. Le projet n'évoluera probablement que de façon mineure."," »",[10,25,26,27,31,32,35],{},"Je me suis rarement autant trompé. Deux ans plus tard, StreamTrackr est devenu ",[28,29,30],"strong",{},"mon plus gros projet",", celui sur lequel j'ai passé le plus de temps, et surtout le premier qui me rapporte réellement de l'argent : environ ",[28,33,34],{},"400 $ de MRR"," au moment où j'écris ces lignes. À l'échelle d'une entreprise, c'est anecdotique. Pour un side project né d'un widget que j'avais bricolé pour mes propres streams RetroAchievements, c'est énorme, et ça change complètement ma façon de voir ce que je fais le soir et le week-end.",[10,37,38],{},"Cet article est long, parce qu'il y a beaucoup à raconter : la refonte, les consoles, la décision de rendre une partie payante, l'app compagnon, et les coulisses d'un service qui tourne en production avec de vrais streamers dessus.",[10,40,41],{},[42,43],"img",{"alt":44,"src":45},"StreamTrackr aujourd'hui","/images/StreamTrackr/pro.webp",[47,48,50],"h2",{"id":49},"petit-rappel-doù-on-vient","Petit rappel : d'où on vient",[10,52,53,54,57],{},"StreamTrackr, en 2024, c'était ça : un widget qui affichait ma progression RetroAchievements pendant mes streams, puis Steam quelques semaines plus tard. Pas de compte, pas de base de données, ",[28,55,56],{},"toute la configuration encodée en base64 dans l'URL",". On réglait ses options, on copiait le lien, on le collait dans OBS, et c'était fini. Quatre thèmes, un rafraîchissement toutes les 30 secondes, et une poignée d'utilisateurs qui venaient du Discord de RetroAchievements.",[10,59,60],{},[42,61],{"alt":62,"src":63},"Le widget d'origine, en 2024","/images/StreamTrackr/Tracker.webp",[10,65,66],{},"Pendant toute l'année 2025, le projet a avancé doucement, au rythme des demandes : des langues supplémentaires en janvier, des corrections de tri et de fuseaux horaires, un widget de feedback en août. Et puis, à la fin de l'été 2025, j'ai fini par m'attaquer à ce que je repoussais depuis un an.",[47,68,70],{"id":69},"playstation-et-xbox-les-api-capricieuses","PlayStation et Xbox : les API « capricieuses »",[10,72,73],{},"Dans mon article de 2024, je disais que la synchronisation avec les API PlayStation et Xbox, « souvent plus complexes et capricieuses », me freinait. J'avais raison d'être méfiant. Mais c'était de loin la demande la plus fréquente, alors j'y suis allé, et les deux plateformes ont été intégrées en quelques jours fin août 2025, puis officialisées avec la version 1.1 en novembre.",[10,75,76],{},"Ce que j'ai appris en chemin :",[78,79,80,91,101],"ul",{},[81,82,83,86,87,90],"li",{},[28,84,85],{},"PlayStation n'a pas d'API publique."," On passe par un jeton NPSSO, celui que le site de Sony utilise lui-même, qu'il faut renouveler régulièrement, et qui peut être invalidé sans prévenir. Les jeux PS3 et PS4 n'ont pas la même structure de trophées que les PS5, et le résumé de trophées livré avec le profil est ",[28,88,89],{},"un instantané que Sony rafraîchit paresseusement",", parfois avec plusieurs heures de retard. De quoi figer le compteur d'un streamer en plein live si on lit la mauvaise source.",[81,92,93,96,97,100],{},[28,94,95],{},"Xbox, c'est encore plus subtil."," Le gamerscore est la seule donnée fiable. Les autres chiffres viennent de l'historique de titres, qui est une fenêtre de récence : elle couvre la quasi-totalité d'un profil ordinaire, mais seulement une partie d'un collectionneur à plusieurs millions de gamerscore. L'API ne renvoie que 1 000 titres, et affiche « zéro succès » sur beaucoup de jeux. Conclusion : ",[28,98,99],{},"un jeu terminé à 100 % se détecte au gamerscore, jamais au nombre de succès."," Microsoft a aussi cassé silencieusement la recherche par gamertag un beau matin, et les icônes de jeux Xbox, en 16:9, s'affichaient étirées en carré.",[81,102,103,106],{},[28,104,105],{},"Les profils privés"," existent sur toutes les plateformes, et il a fallu apprendre à afficher un message utile plutôt qu'un overlay vide.",[10,108,109,110,113],{},"Une règle produit est sortie de tout ça, et j'y tiens : ",[28,111,112],{},"un emplacement sans valeur n'est jamais remplacé par un 0."," Quand un compte Xbox restreint son historique, l'API renvoie une liste vide avec un code 200. Afficher « 0 succès » à côté d'un gamerscore réel serait un mensonge. Même règle quand RetroAchievements nous limite, ou quand un comptage PSN échoue : la case disparaît, elle ne ment pas.",[47,115,117],{"id":116},"la-grande-refonte","La grande refonte",[10,119,120],{},"Fin 2025, j'ai posé une bannière « StreamTrackr Pro bientôt » sur le site, sans trop savoir ce qu'il y aurait derrière. Puis j'ai écrit un document de specs qui a fini par faire plus de 5 000 lignes. Dedans, tout ce que le projet n'était pas encore : des comptes utilisateurs, des liens de tracker persistants au lieu de la config en base64, une vraie personnalisation, des intégrations Twitch et Discord, des statistiques, et un moyen de payer.",[10,122,123],{},"Le chantier technique qui va avec :",[78,125,126,133,139,146,153,163],{},[81,127,128,129,132],{},"Migration de ",[28,130,131],{},"Nuxt 3 vers Nuxt 4",", de Tailwind 3 vers 4, et de Nuxt UI 2 vers 3, composant par composant.",[81,134,135,138],{},[28,136,137],{},"Supabase"," pour la base, l'authentification et le temps réel, avec du RLS sur toutes les tables. Comme sur mes autres projets, c'est ce qui m'a permis d'aller vite.",[81,140,141,142,145],{},"L'API, déjà séparée en ",[28,143,144],{},"NestJS"," depuis l'été 2025, s'est étoffée jusqu'à une trentaine de modules : un par plateforme, un pour le paiement, un pour Twitch, un pour Discord, un pour les exports, un pour l'affiliation…",[81,147,148,149,152],{},"Trois canaux temps réel qui coexistent : Supabase Realtime pour synchroniser la configuration, Socket.io pour les compteurs, et des ",[28,150,151],{},"SSE"," pour pousser les nouveaux succès vers les overlays dans OBS.",[81,154,155,156,162],{},"Un nouveau domaine, ",[14,157,161],{"href":158,"rel":159},"https://streamtrackr.com",[160],"nofollow","streamtrackr.com",", à la place du sous-domaine sur PlayFan.",[81,164,165,166,169],{},"Et les ",[28,167,168],{},"huit langues"," (anglais, français, italien, espagnol, allemand, néerlandais, portugais brésilien, polonais) à maintenir sur chaque nouvelle page. C'est le point le plus fastidieux du projet, et aussi l'un des plus rentables : une bonne partie des streamers qui m'écrivent ne sont pas francophones.",[10,171,172],{},"Pour les utilisateurs de l'ancien widget, rien n'a cassé : les anciens liens en base64 continuent de fonctionner, avec un thème sombre recalé pixel par pixel sur l'ancien rendu pour que la migration soit invisible.",[47,174,176],{"id":175},"le-14-mars-2026-streamtrackr-pro","Le 14 mars 2026 : StreamTrackr Pro",[10,178,179,180,183,184,187],{},"J'ai hésité longtemps sur le modèle. Ma première idée, dans les specs, c'était ",[28,181,182],{},"un paiement unique à 19,99 €",". Puis j'ai envisagé deux paliers, un Pro et un Pro « + Twitch ». J'ai fini par tout simplifier : ",[28,185,186],{},"un seul Pro",", Twitch et Discord inclus, avec trois façons de payer :",[78,189,190,196,202],{},[81,191,192,195],{},[28,193,194],{},"2,99 € par mois",", avec le premier mois offert (carte bancaire requise, un essai par compte) ;",[81,197,198,201],{},[28,199,200],{},"24,99 € par an",", soit environ 30 % de réduction ;",[81,203,204,207],{},[28,205,206],{},"39,99 € à vie",", pour ceux qui n'aiment pas les abonnements.",[10,209,210,211,214],{},"Le prix mensuel n'est pas un hasard : c'est à peu près celui d'un sub Twitch. Je voulais que ça reste un montant qu'un streamer n'a pas besoin de justifier. Et honnêtement, ",[28,212,213],{},"l'offre à vie est celle qui part le mieux",". Je ne l'avais pas anticipé, mais ça se comprend : les streamers en ont marre des abonnements, et 40 € une fois pour toutes, ça se décide vite.",[10,216,217,218,221],{},"Le principe non négociable : ",[28,219,220],{},"tout ce qui faisait StreamTrackr reste gratuit."," Les quatre plateformes, l'overlay, les quatre thèmes de base, les succès trackés, le lien persistant, la sauvegarde cloud. Le Pro ajoute le confort et la profondeur :",[78,223,224,231,238,245,259,270],{},[81,225,226,227,230],{},"un ",[28,228,229],{},"rafraîchissement rapide"," (5 à 10 secondes au lieu de 30) avec un pool de clés API réservé ;",[81,232,233,234,237],{},"le ",[28,235,236],{},"studio de personnalisation"," : on clique sur n'importe quel élément de l'overlay (badge, barre de progression, texte, image) et un panneau permet d'en changer la typographie, les couleurs, la taille, l'espacement ;",[81,239,240,241,244],{},"des ",[28,242,243],{},"thèmes et animations"," personnalisés, puis à partir de mai, 14 templates designés ;",[81,246,240,247,250,251,254,255,258],{},[28,248,249],{},"alertes de déblocage"," avec son et effets, des ",[28,252,253],{},"objectifs de stream",", des ",[28,256,257],{},"stats de session"," ;",[81,260,261,262,265,266,269],{},"les intégrations ",[28,263,264],{},"Twitch"," (titre et catégorie mis à jour automatiquement, messages dans le chat, bot dédié, clips, marqueurs de VOD, commandes personnalisées) et ",[28,267,268],{},"Discord"," (webhooks, embeds, paliers) ;",[81,271,240,272,275,276,279,280,284],{},[28,273,274],{},"exports en images"," pour les réseaux sociaux et, depuis juin, des ",[28,277,278],{},"pages de récap publiques"," de chaque session, avec une commande ",[281,282,283],"code",{},"!recap"," dans le chat.",[10,286,287,288,291,292,295],{},"Le mois de mars 2026 a été le plus dense de toute l'histoire du projet : ",[28,289,290],{},"près de 90 commits",", pour Stripe et Stripe Tax (la TVA européenne, calculée automatiquement), les webhooks, les factures, un planificateur d'expiration des licences, un système d'essai gratuit, une page de statut des services, et un programme d'affiliation à ",[28,293,294],{},"30 % de commission",", devenu récurrent en mai. Et surtout, dès la première semaine, un utilisateur Pro m'a remonté six bugs d'un coup sur le tracker. Ce jour-là, j'ai compris que vendre quelque chose change la nature des retours : ils deviennent précis, exigeants, et infiniment plus utiles.",[47,297,299],{"id":298},"le-companion-contourner-steam","Le Companion : contourner Steam",[10,301,302,303,306],{},"Le vrai problème de Steam, c'est la latence. D'abord parce qu'il faut interroger l'API régulièrement, ensuite et surtout parce que ",[28,304,305],{},"Valve regroupe les succès côté serveur"," : un déblocage peut mettre plusieurs minutes à apparaître dans l'API. Pour un overlay qui se prétend « en direct », c'est rédhibitoire, et je l'écris noir sur blanc sur la page de tarifs.",[10,308,309,310,313,314,317],{},"J'ai donc écrit ",[28,311,312],{},"StreamTrackr Companion",", une petite app Windows en ",[28,315,316],{},"Go"," qui vit dans la barre des tâches, sortie en mai 2026. Elle ne touche pas au jeu, et c'est un choix d'architecture, pas juste une promesse :",[78,319,320,323,326,333],{},[81,321,322],{},"pas de SDK Steamworks, pas de DLL chargée, pas de handle sur le processus du jeu, pas d'injection ;",[81,324,325],{},"elle lit une clé de registre pour savoir quel jeu tourne, et deux fichiers que Steam écrit pour sa propre interface : le schéma des succès et l'état de déblocage de l'utilisateur, dans le format binaire de Valve, que j'ai dû parser à la main ;",[81,327,328,329,332],{},"elle surveille la date de modification du fichier ",[28,330,331],{},"quatre fois par seconde",". Steam le réécrit à chaque fois qu'un jeu enregistre ses stats, c'est-à-dire pile au moment où la notification apparaît à l'écran ;",[81,334,335],{},"quand un bit passe de 0 à 1, elle envoie le succès à StreamTrackr, qui le diffuse vers l'overlay, le chat Twitch, Discord et les stats.",[10,337,338,339,342],{},"Résultat : ",[28,340,341],{},"moins d'une seconde"," entre le déblocage et l'affichage sur le stream. Pour situer, un logiciel vendu sur le Steam Store fait la même chose en initialisant le SDK Steam contre le jeu en cours. Le Companion prend la route la plus stricte, il ne touche à rien. Il est open source sous licence MIT, se met à jour tout seul, et le jumelage avec le compte passe par un flux façon OAuth sur une adresse locale.",[10,344,345,346,349],{},"Un détail dont je suis content, et qui date du mois d'août : la pastille de couleur dans la barre des tâches ne dit plus « connecté », elle dit ",[28,347,348],{},"« délivré »",". Vert quand le dernier succès a bien été accepté et affiché, ambre quand StreamTrackr n'a nulle part où le mettre (aucun overlay ouvert, tracker sur une autre plateforme), rouge quand plus rien ne peut arriver. Être connecté ne sert à rien si le succès n'apparaît pas sur le stream.",[47,351,353],{"id":352},"les-coulisses-de-la-prod","Les coulisses de la prod",[10,355,356],{},"C'est la partie que j'ai le plus envie de raconter, parce que c'est là que j'ai le plus appris. Faire un outil qui marche sur mon PC, je savais. Faire tourner un service avec des streamers en live dessus, à toute heure, c'est un autre métier.",[10,358,359,362,363,366,367,370],{},[28,360,361],{},"RetroAchievements limite fortement les appels."," Une semaine après le lancement Pro, j'ai analysé deux heures de logs : sur 112 utilisateurs RA actifs, mon pool de huit clés API obtenait ",[28,364,365],{},"74 % de réussite",", avec près de 200 échecs définitifs et plus de 2 600 appels « rien de nouveau » faits pour rien. L'API n'a pas de webhook, le polling est obligatoire, et les limites sont par clé. J'ai donc mis en place une file d'attente avec rotation, séparé les appels de fond des appels interactifs, remplacé les endpoints lourds (certains renvoient jusqu'à 150 Ko par appel) par des pré-vérifications légères, et surtout ",[28,368,369],{},"réservé un pool de clés aux abonnés Pro",", pour que les utilisateurs gratuits ne consomment jamais le quota de ceux qui paient.",[10,372,373,376,377,380,381,384],{},[28,374,375],{},"Le bug des 3 166 succès."," Un utilisateur s'est retrouvé avec 3 166 succès dans ses statistiques, au lieu d'une trentaine. Une seule session avait généré 2 990 événements, dont un succès répété ",[28,378,379],{},"238 fois",", le tout inséré en ",[28,382,383],{},"onze secondes",", plus de deux heures après la fin du stream. La cause : le cache de déduplication vivait en mémoire, ne survivait pas aux redémarrages de l'API, et n'était pas rechargé depuis la base quand une session reprenait. Au redémarrage, tous les overlays se reconnectaient en même temps, et chacun réinsérait la liste complète. Corrigé par une réhydratation du cache et une contrainte d'unicité en base, parce qu'un cache ne remplace jamais une contrainte.",[10,386,387,390,391,394,395,402,403,406],{},[28,388,389],{},"La fuite mémoire."," Le même jour, je découvrais que l'API consommait ",[28,392,393],{},"2,3 Go de RAM au bout de 24 heures",", au lieu des 200 Mo attendus. J'ai compté ",[28,396,397,398,401],{},"onze ",[281,399,400],{},"Map"," dispersées"," dans les services, utilisées comme caches sans limite de taille ni éviction : statuts Twitch, jetons PSN, raretés Steam, événements Stripe déjà traités… Tout a été centralisé dans un module de cache avec LRU et TTL, et j'ai ajouté ",[28,404,405],{},"Prometheus et Grafana"," pour ne plus découvrir ce genre de choses par hasard.",[10,408,409,412,413,416,417,420],{},[28,410,411],{},"L'incident de facturation du 16 juillet."," Un client dont le renouvellement avait échoué s'est réabonné via la page de paiement au lieu de corriger sa carte, et comme mon code réutilisait le même client Stripe, les abonnements se sont ",[28,414,415],{},"empilés"," au lieu de se remplacer. Il s'est retrouvé avec six abonnements en parallèle. Aujourd'hui, un paiement est refusé si le client a déjà un abonnement vivant, et il est redirigé vers le portail de facturation. La leçon est simple : ",[28,418,419],{},"le chemin d'erreur d'un paiement est un chemin utilisateur comme un autre",", et je ne l'avais jamais testé.",[10,422,423,426,427,430,431,434],{},[28,424,425],{},"Et une collection de plus petits."," Le bot Twitch dont l'abonnement au chat expirait silencieusement côté Twitch, laissant les commandes muettes jusqu'au redémarrage. La commande ",[281,428,429],{},"!progress"," qui répondait sur le mauvais jeu quand plusieurs trackers tournaient. Les overlays OBS dont la connexion SSE avait des trous, corrigés en août ",[28,432,433],{},"et mesurés",", parce qu'on ne corrige pas ce qu'on ne mesure pas. Une panne de Sony qu'il ne faut jamais lire comme « ce joueur n'a rien gagné ». Et la première version des liens de tracker, à 8 caractères, passée à 16 avec un avertissement au copier-coller, parce qu'un streamer peut afficher l'URL de son overlay à l'écran sans s'en rendre compte.",[10,436,437,440,441,444],{},[28,438,439],{},"Le piège maison."," Ma propre architecture m'a aussi joué des tours. Ajouter un simple élément personnalisable à l'overlay demande d'aligner ",[28,442,443],{},"cinq tables"," indépendantes dans le code. En rater une ne casse rien de visible : ça produit un élément « à moitié vivant ». Le bloc de stats de profil s'affichait, se cliquait, se sauvegardait… mais sa personnalisation était inerte, et l'inspecteur s'ouvrait vide. J'ai fini par écrire des tests-matrices qui font échouer la CI dès qu'une table décroche. J'aurais dû commencer par là.",[47,446,448],{"id":447},"ce-que-ça-ma-appris","Ce que ça m'a appris",[10,450,451],{},"Quelques convictions, avec le recul :",[78,453,454,460,466,472],{},[81,455,456,459],{},[28,457,458],{},"Les retours des streamers sont la meilleure source d'idées."," Presque tout ce qui existe dans le Pro vient d'une demande. La catégorie Twitch automatique, les options de trophée Platine, les récaps publics : je n'aurais inventé aucun de ces trois-là seul.",[81,461,462,465],{},[28,463,464],{},"Rendre payant a rendu le projet meilleur."," Pas seulement parce que ça finance le serveur et les clés API, mais parce que les gens qui paient signalent les bugs avec une précision que je n'avais jamais eue.",[81,467,468,471],{},[28,469,470],{},"Le gratuit doit rester entier."," La FAQ du site dit que la version gratuite restera gratuite avec toutes ses fonctionnalités, et je m'y tiens. Le Pro vend la profondeur, pas le droit d'utiliser l'outil.",[81,473,474,477],{},[28,475,476],{},"La production, c'est du monitoring."," Grafana, une page de statut publique, des logs que l'on peut grepper, des alertes. Chaque bug spectaculaire de cette liste aurait été détecté plus tôt avec le monitoring que j'ai maintenant.",[47,479,481],{"id":480},"et-maintenant","Et maintenant ?",[10,483,484],{},"Je continue au rythme des retours, une version toutes les deux à trois semaines depuis mars. Le prochain chantier, c'est de rendre le Pro plus visible pour ceux qui utilisent le gratuit depuis des mois sans savoir ce qu'ils ratent, de continuer à fiabiliser PSN et Xbox, qui restent les plateformes les plus fragiles, et d'étendre les templates d'overlay.",[10,486,487],{},"Et quelque part, de savourer un peu. Ce widget bricolé un dimanche de mai 2024 pour mes streams rétro est devenu un outil que des streamers utilisent tous les jours, dans huit langues, et qui me paie. Ce n'est pas rien.",[10,489,490,491],{},"J'ai mis à jour la fiche projet avec tous les détails techniques, ",[14,492,493],{"href":16},"👉 c'est par ici !",{"title":495,"searchDepth":496,"depth":496,"links":497},"",2,[498,499,500,501,502,503,504,505],{"id":49,"depth":496,"text":50},{"id":69,"depth":496,"text":70},{"id":116,"depth":496,"text":117},{"id":175,"depth":496,"text":176},{"id":298,"depth":496,"text":299},{"id":352,"depth":496,"text":353},{"id":447,"depth":496,"text":448},{"id":480,"depth":496,"text":481},"2026-08-27T09:00:00.000Z","En 2024, j'écrivais que StreamTrackr n'évoluerait « probablement que de façon mineure ». Raté. 😄 Quatre plateformes, huit langues, une offre Pro lancée en mars, une app compagnon en Go… et aujourd'hui, environ 400 $ de revenus mensuels récurrents. Je vous raconte tout, les bons choix comme les bugs qui m'ont fait suer.","md",{"readingTime":510},{"text":511,"minutes":512,"time":513,"words":514},"14 min read",13.31,798600,2662,true,"/blog/streamtrackr-pro-mon-premier-projet-rentable",{"title":5,"description":507},"blog/streamtrackr-pro-mon-premier-projet-rentable",[520,521,522],"SaaS","Streaming","Projet","lCOnTBu8m8M4LKPwz17eLKH-QfWSFejM9QwTC-4psrw",1787859225500]