[{"data":1,"prerenderedAt":1055},["ShallowReactive",2],{"profil-footer":3,"i-lucide:menu":114,"i-simple-icons:github":119,"i-simple-icons:linkedin":121,"i-lucide:mail":124,"projet-\u002Fprojets\u002Fglobe-satellites":126,"projets-navigation":206,"i-lucide:arrow-left":1049,"i-lucide:check":1051,"i-lucide:arrow-right":1053},{"id":4,"accroche":5,"apropos":6,"competences":11,"cv":71,"email":72,"extension":73,"localisation":74,"meta":75,"nom":76,"parcours":77,"reseaux":99,"stem":112,"titre":80,"__hash__":113},"profil\u002Fprofil.yml","Je conçois et développe des applications web de bout en bout — de la base de données au pixel — et des outils d'IA qui s'y branchent. Vue \u002F Nuxt côté interface, Python et Node côté serveur, Docker et VPS pour la mise en production.",[7,8,9,10],"Développeur full-stack, je construis des produits complets plutôt que des morceaux de produits : modèle de données, API, interface, déploiement et supervision. C'est cette vue d'ensemble qui m'intéresse — comprendre comment une décision de schéma se répercute jusqu'à l'expérience utilisateur.","Mes projets personnels tournent souvent autour de la donnée géographique et du temps réel : cartographie de feux de forêt à partir de données satellitaires, fusion de sources publiques immobilières, suivi de satellites en orbite. J'aime les sujets où la donnée brute est ingrate et où le travail consiste à la rendre lisible.","Je travaille en Docker de bout en bout, j'héberge sur mes propres serveurs, et je documente ce que je construis — parce qu'un projet qu'on ne peut pas reprendre six mois plus tard n'est pas vraiment terminé.","Je ne suis pas venu au développement par l'informatique, mais par l'objet : conception de produits industriels, puis 3D temps réel. J'y ai pris le goût des contraintes concrètes et de la géométrie, et l'habitude de partir d'un cahier des charges plutôt que d'une techno. Le code est arrivé comme le moyen le plus direct d'automatiser ce qui me ralentissait — et n'en est jamais reparti.",[12,21,30,39,47,55,62],{"categorie":13,"icon":14,"items":15},"Front-end","lucide:layout-dashboard",[16,17,18,19,20],"Vue 3","Nuxt","TypeScript","Tailwind CSS","MapLibre GL",{"categorie":22,"icon":23,"items":24},"Back-end","lucide:server",[25,26,27,28,29],"Python","FastAPI","Node.js","AdonisJS","PHP",{"categorie":31,"icon":32,"items":33},"Données","lucide:database",[34,35,36,37,38],"PostgreSQL","PostGIS","MongoDB","Redis","SQLite",{"categorie":40,"icon":41,"items":42},"IA & Data","lucide:brain-circuit",[43,44,45,46],"TensorFlow","Keras","Vertex AI","pandas",{"categorie":48,"icon":49,"items":50},"Infrastructure","lucide:container",[51,52,53,54],"Docker","nginx","Caddy","GitHub Actions",{"categorie":56,"icon":57,"items":58},"Mobile","lucide:smartphone",[59,60,61],"SwiftUI","SwiftData","iOS",{"categorie":63,"icon":64,"items":65},"Méthode & produit","lucide:git-branch",[66,67,68,69,70],"GitHub Flow","Tests","Documentation","Product Ownership","Agile","","rs.szmygiel@gmail.com","yml","Bordeaux, France",{},"Ronan Szmygiel",[78,84,89,95],{"periode":79,"titre":80,"organisation":81,"type":82,"description":83},"2022 — aujourd'hui","Développeur IA & Web \u002F Product Owner","Cosmo5","experience","Conception et développement d'outils SaaS plug & play pour les entités du groupe Cosmo5, d'abord chez FeedManager puis chez SnapFeat. Product Owner d'une solution de type CRM et de suivi de projet mutualisée pour tout le groupe, et développement d'outils d'IA destinés à optimiser les process internes et clients. Vue, Node.js, PHP, MongoDB, Python, TensorFlow et Vertex AI.",{"periode":85,"titre":86,"organisation":87,"type":82,"description":88},"2020 — 2022","Consultant CPQ \u002F CRM & 3D temps réel","ITCelerator","Développement, mise en place et paramétrage de progiciels CPQ — Salesforce, Apttus Conga, KBMax, Threekit — avec avant-vente, POC et suivi de projet. En amont, sur le volet 3D temps réel : analyse et optimisation de la chaîne qui mène de la CAO volumique au moteur temps réel, et garantie de la qualité visuelle des configurateurs livrés.",{"periode":90,"titre":91,"organisation":92,"type":93,"description":94},"2021 — 2023","Master Architecte logiciel — développeur d'applications","EPITECH","formation","Titre de niveau 7 en programmation et architecture logicielle, suivi en alternance avec le poste chez Cosmo5.",{"periode":96,"titre":97,"organisation":92,"type":93,"description":98},"2020 — 2021","Pré-MSc Pro — programmation informatique","Année de spécialisation en développement, préalable au Master.",[100,104,108],{"nom":101,"url":102,"icon":103},"GitHub","https:\u002F\u002Fgithub.com\u002Fnanro22","simple-icons:github",{"nom":105,"url":106,"icon":107},"LinkedIn","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fszmygiel-ronan\u002F","simple-icons:linkedin",{"nom":109,"url":110,"icon":111},"Email","mailto:rs.szmygiel@gmail.com","lucide:mail","profil","s-LvnXFPWm79Qf71gMmV-pPLKLYxCobON7TnYH68ZOw",{"left":115,"top":115,"width":116,"height":116,"rotate":115,"vFlip":117,"hFlip":117,"body":118},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"\u002F>",{"left":115,"top":115,"width":116,"height":116,"rotate":115,"vFlip":117,"hFlip":117,"body":120},"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"left":115,"top":115,"width":116,"height":116,"rotate":115,"vFlip":117,"hFlip":117,"body":122,"hidden":123},"\u003Cpath fill=\"currentColor\" d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037c-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85c3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.06 2.06 0 0 1-2.063-2.065a2.064 2.064 0 1 1 2.063 2.065m1.782 13.019H3.555V9h3.564zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0z\"\u002F>",true,{"left":115,"top":115,"width":116,"height":116,"rotate":115,"vFlip":117,"hFlip":117,"body":125},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m22 7l-8.991 5.727a2 2 0 0 1-2.009 0L2 7\"\u002F>\u003Crect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"\u002F>\u003C\u002Fg>",{"id":127,"title":128,"body":129,"cover":71,"demo":71,"description":186,"extension":187,"featured":117,"highlights":188,"meta":192,"navigation":123,"path":193,"rang":194,"repo":71,"role":195,"seo":196,"status":197,"stem":198,"tags":199,"type":203,"year":204,"__hash__":205},"projets\u002Fprojets\u002Fglobe-satellites.md","Globe Satellites",{"type":130,"value":131,"toc":180},"minimark",[132,137,141,144,148,158,166,169,173],[133,134,136],"h2",{"id":135},"le-projet","Le projet",[138,139,140],"p",{},"Plusieurs milliers de satellites actifs tournent au-dessus de nos têtes, et leurs orbites\nsont publiques. Celestrak diffuse les éléments orbitaux au format TLE (Two-Line Element),\nqui suffisent à calculer la position de n'importe quel objet à n'importe quel instant.",[138,142,143],{},"Globe Satellites affiche ce ballet sur un globe 3D, actualisé toutes les cinq secondes.",[133,145,147],{"id":146},"architecture","Architecture",[149,150,155],"pre",{"className":151,"code":153,"language":154},[152],"language-text","Navigateur — Globe 3D (Globe.gl)\n      ↕ WebSocket\nFrontend nginx — fichiers statiques Vue 3, proxy \u002Fws\n      ↓ réseau Docker\nBackend FastAPI — propagation orbitale (Skyfield)\n","text",[156,157,153],"code",{"__ignoreMap":71},[138,159,160,161,165],{},"Le choix structurant est de ",[162,163,164],"strong",{},"calculer côté serveur",". La propagation orbitale SGP4 pour\nplusieurs milliers d'objets, cinq fois par minute, n'est pas un travail pour le\nnavigateur — d'autant que tous les clients connectés partagent exactement le même\nrésultat. Le serveur calcule une fois, diffuse à tout le monde par WebSocket, et le\nclient ne fait que du rendu.",[138,167,168],{},"Les TLE sont rafraîchis périodiquement depuis Celestrak : ils se dégradent en précision\nau fil des jours, une propagation sur des éléments vieux d'une semaine dérive\nsensiblement.",[133,170,172],{"id":171},"contrainte-matérielle","Contrainte matérielle",[138,174,175,176,179],{},"Le projet est pensé pour un ",[162,177,178],{},"Raspberry Pi 4 en ARM64",". Cette contrainte a orienté\nplusieurs décisions : image Docker multi-architecture, calculs vectorisés avec NumPy\nplutôt qu'en boucle Python, et diffusion d'un état partagé unique plutôt que d'un calcul\npar client connecté.",{"title":71,"searchDepth":181,"depth":181,"links":182},2,[183,184,185],{"id":135,"depth":181,"text":136},{"id":146,"depth":181,"text":147},{"id":171,"depth":181,"text":172},"Globe 3D interactif affichant en temps réel la position des satellites actifs en orbite terrestre, conçu pour tourner sur un Raspberry Pi.","md",[189,190,191],"Positions recalculées toutes les 5 secondes à partir des données TLE Celestrak","Propagation orbitale avec Skyfield côté serveur, rendu WebGL côté client","Image ARM64 tournant en continu sur un Raspberry Pi 4",{},"\u002Fprojets\u002Fglobe-satellites",4,"Conception et développement full-stack",{"title":128,"description":186},"En production","projets\u002Fglobe-satellites",[16,200,26,25,201,51,202],"Globe.gl","WebSocket","Raspberry Pi","Web",2025,"XgiN1lZLGHta_S-_cksn8kEHMFzzXVpfRVbqWr9vLEc",[207,268,374,411,564,658,711,846],{"id":208,"title":209,"body":210,"cover":71,"demo":71,"description":254,"extension":187,"featured":117,"highlights":255,"meta":259,"navigation":123,"path":260,"rang":261,"repo":71,"role":195,"seo":262,"status":263,"stem":264,"tags":265,"type":203,"year":266,"__hash__":267},"projets\u002Fprojets\u002Fcatan.md","Catan",{"type":130,"value":211,"toc":249},[212,214,217,219,225,228,231,235,246],[133,213,136],{"id":135},[138,215,216],{},"Une version numérique de Catan, jouable en multijoueur dans le navigateur : plateau\ngénéré aléatoirement, placement des colonies et des routes, production de ressources,\néchanges entre joueurs, voleur et décompte des points de victoire.",[133,218,147],{"id":146},[138,220,221,224],{},[162,222,223],{},"Stack"," : Vue 3 · FastAPI · PostgreSQL · WebSocket",[138,226,227],{},"L'état de la partie vit sur le serveur, jamais dans le client. Chaque action envoyée par\nun joueur est validée côté serveur — est-ce son tour, a-t-il les ressources, l'emplacement\nest-il légal — avant d'être appliquée puis rediffusée à tous les participants.",[138,229,230],{},"C'est la seule architecture défendable pour un jeu multijoueur : un client qui calcule\nlui-même ce qu'il a le droit de faire est un client qu'on peut modifier.",[133,232,234],{"id":233},"ce-que-le-jeu-apprend","Ce que le jeu apprend",[138,236,237,238,241,242,245],{},"Catan est un excellent exercice de modélisation. Le plateau est un pavage hexagonal où\nles colonies se placent sur les ",[162,239,240],{},"sommets"," et les routes sur les ",[162,243,244],{},"arêtes"," — trois\nsystèmes de coordonnées cohabitent donc, et la moitié du travail consiste à naviguer\nproprement entre eux : quelles tuiles touchent ce sommet, quelles arêtes partent d'ici,\nquels sommets sont trop proches pour accueillir une nouvelle colonie.",[138,247,248],{},"Une fois cette géométrie posée correctement, les règles du jeu deviennent presque\ntriviales à implémenter. Posée de travers, chaque règle devient un cas particulier.",{"title":71,"searchDepth":181,"depth":181,"links":250},[251,252,253],{"id":135,"depth":181,"text":136},{"id":146,"depth":181,"text":147},{"id":233,"depth":181,"text":234},"Adaptation web multijoueur du jeu de société Catan, jouable à plusieurs dans un navigateur en temps réel.",[256,257,258],"Partie multijoueur synchronisée en temps réel par WebSocket","Règles du jeu et validation des coups entièrement côté serveur","Démarrage complet en une commande docker compose",{},"\u002Fprojets\u002Fcatan",5,{"title":209,"description":254},"Terminé","projets\u002Fcatan",[16,26,25,34,201,51],2024,"_81X4hld_ociFxaYrD8sPFCtxtidiinrmLd5uMPKcqQ",{"id":269,"title":270,"body":271,"cover":71,"demo":71,"description":358,"extension":187,"featured":123,"highlights":359,"meta":363,"navigation":123,"path":364,"rang":365,"repo":71,"role":195,"seo":366,"status":367,"stem":368,"tags":369,"type":203,"year":372,"__hash__":373},"projets\u002Fprojets\u002Fdatabridge-supermap.md","DataBridge SuperMap",{"type":130,"value":272,"toc":351},[273,277,280,283,287,290,292,319,330,337,341,344,348],[133,274,276],{"id":275},"le-problème","Le problème",[138,278,279],{},"Les données immobilières françaises sont publiques et gratuites. Elles sont aussi\néparpillées : les transactions dans DVF, la géométrie des parcelles dans le cadastre, les\ncaractéristiques du bâti dans la BDNB, la performance énergétique dans les DPE, la\ndémographie à l'INSEE, l'exposition aux risques ailleurs encore.",[138,281,282],{},"Chacune a son format, sa granularité et son identifiant pivot. Croiser « le prix au m²\ndes maisons construites avant 1975 avec un DPE F ou G dans un secteur inondable » demande\ndonc un travail de fusion préalable considérable.",[133,284,286],{"id":285},"lobjectif-produit","L'objectif produit",[138,288,289],{},"Un moteur d'estimation de prix immobilier — la carte est le support d'exploration, mais\nl'objectif est de nourrir un modèle avec des caractéristiques réellement croisées.",[133,291,147],{"id":146},[293,294,295,302,308,313],"ul",{},[296,297,298,301],"li",{},[162,299,300],{},"Frontend"," : Nuxt 3 + MapLibre GL — exploration cartographique, filtres, backoffice",[296,303,304,307],{},[162,305,306],{},"Backend"," : FastAPI + SQLAlchemy, avec Celery pour les traitements longs",[296,309,310,312],{},[162,311,31],{}," : PostgreSQL \u002F PostGIS pour le spatial, Redis comme broker",[296,314,315,318],{},[162,316,317],{},"Infra"," : docker-compose, workers séparés par file d'attente",[138,320,321,322,325,326,329],{},"Les workers sont scindés en deux files : ",[156,323,324],{},"imports"," pour l'ingestion des sources, et\n",[156,327,328],{},"mutations"," pour les rebuilds, l'enrichissement, la génération de tuiles et les\ntraitements ML. Cette séparation évite qu'un import de plusieurs heures bloque un\nrecalcul de tuiles de quelques minutes.",[138,331,332,333,336],{},"Un backoffice ",[156,334,335],{},"\u002Fadmin"," pilote les imports et suit l'état des jobs.",[133,338,340],{"id":339},"méthode","Méthode",[138,342,343],{},"Le projet s'appuie sur une documentation en dix fichiers — architecture, sources, modèle\nde données, pipelines, API, frontend, backoffice, runbook, roadmap — tenue à jour à\nchaque évolution significative. Le runbook consigne notamment les pièges d'infrastructure\nappris à la dure, ce qui évite de les réapprendre.",[133,345,347],{"id":346},"ce-que-jen-retire","Ce que j'en retire",[138,349,350],{},"Sur ce type de projet, la difficulté n'est jamais l'algorithme : c'est la réconciliation\nd'identifiants entre référentiels qui ne se sont jamais parlé. Une parcelle cadastrale et\nun bâtiment BDNB ne partagent pas de clé — il faut la reconstruire spatialement, et\naccepter un taux d'appariement imparfait.",{"title":71,"searchDepth":181,"depth":181,"links":352},[353,354,355,356,357],{"id":275,"depth":181,"text":276},{"id":285,"depth":181,"text":286},{"id":146,"depth":181,"text":147},{"id":339,"depth":181,"text":340},{"id":346,"depth":181,"text":347},"Carte interactive de France fusionnant les données publiques immobilières — DVF, cadastre, BDNB, DPE, INSEE, risques — au service d'un moteur d'estimation de prix.",[360,361,362],"Sept sources de données publiques fusionnées sur un référentiel commun","Pipelines d'import asynchrones supervisés depuis un backoffice","Tuiles vectorielles générées à la volée pour la France entière",{},"\u002Fprojets\u002Fdatabridge-supermap",3,{"title":270,"description":358},"En développement","projets\u002Fdatabridge-supermap",[370,20,26,371,35,37],"Nuxt 3","Celery",2026,"8yIQyq0ac7EwFw52N9CKAkmabligD4xyIHvsCL_VVXE",{"id":127,"title":128,"body":375,"cover":71,"demo":71,"description":186,"extension":187,"featured":117,"highlights":407,"meta":408,"navigation":123,"path":193,"rang":194,"repo":71,"role":195,"seo":409,"status":197,"stem":198,"tags":410,"type":203,"year":204,"__hash__":205},{"type":130,"value":376,"toc":402},[377,379,381,383,385,390,394,396,398],[133,378,136],{"id":135},[138,380,140],{},[138,382,143],{},[133,384,147],{"id":146},[149,386,388],{"className":387,"code":153,"language":154},[152],[156,389,153],{"__ignoreMap":71},[138,391,160,392,165],{},[162,393,164],{},[138,395,168],{},[133,397,172],{"id":171},[138,399,175,400,179],{},[162,401,178],{},{"title":71,"searchDepth":181,"depth":181,"links":403},[404,405,406],{"id":135,"depth":181,"text":136},{"id":146,"depth":181,"text":147},{"id":171,"depth":181,"text":172},[189,190,191],{},{"title":128,"description":186},[16,200,26,25,201,51,202],{"id":412,"title":413,"body":414,"cover":71,"demo":71,"description":552,"extension":187,"featured":123,"highlights":553,"meta":557,"navigation":123,"path":558,"rang":181,"repo":71,"role":195,"seo":559,"status":367,"stem":560,"tags":561,"type":203,"year":372,"__hash__":563},"projets\u002Fprojets\u002Fpyro-radar.md","Pyro Radar",{"type":130,"value":415,"toc":546},[416,420,423,426,430,504,507,511,517,523,529,535,541,543],[133,417,419],{"id":418},"lidée","L'idée",[138,421,422],{},"Les données de détection d'incendies sont publiques, gratuites et abondantes — la NASA,\nl'ESA, la NOAA et la JAXA les diffusent en continu. Elles sont aussi diffusées dans des\nformats hétérogènes, à des cadences différentes, avec des couvertures géographiques qui\nse recouvrent partiellement.",[138,424,425],{},"Pyro Radar fusionne ces flux en une carte unique, mondiale, rafraîchie en continu.",[133,427,429],{"id":428},"les-sources","Les sources",[431,432,433,449],"table",{},[434,435,436],"thead",{},[437,438,439,443,446],"tr",{},[440,441,442],"th",{},"Source",[440,444,445],{},"Couverture",[440,447,448],{},"Cadence",[450,451,452,464,475,485,495],"tbody",{},[437,453,454,458,461],{},[455,456,457],"td",{},"NASA FIRMS (VIIRS \u002F MODIS)",[455,459,460],{},"Monde",[455,462,463],{},"Passages orbitaux",[437,465,466,469,472],{},[455,467,468],{},"GOES-18 \u002F 19",[455,470,471],{},"Amériques",[455,473,474],{},"10 min",[437,476,477,480,483],{},[455,478,479],{},"Meteosat MTG (LSA SAF)",[455,481,482],{},"Europe \u002F Afrique",[455,484,474],{},[437,486,487,490,493],{},[455,488,489],{},"Himawari-9",[455,491,492],{},"Asie \u002F Océanie",[455,494,474],{},[437,496,497,500,502],{},[455,498,499],{},"Sentinel-3 SLSTR (Copernicus)",[455,501,460],{},[455,503,463],{},[138,505,506],{},"Les satellites géostationnaires apportent la fréquence, les orbites polaires apportent la\nrésolution.",[133,508,510],{"id":509},"le-travail-technique","Le travail technique",[138,512,513,516],{},[162,514,515],{},"Ingestion."," CSV pour FIRMS, NetCDF pour GOES, HDF5 pour MTG : un ingesteur par\nsource normalise vers un schéma commun de détections géolocalisées.",[138,518,519,522],{},[162,520,521],{},"Zones brûlées."," Les détections ponctuelles deviennent des polygones estimés\ndirectement en PostGIS, par lots — charger toutes les zones d'un coup faisait tomber\nPostgres.",[138,524,525,528],{},[162,526,527],{},"Vent."," Les données GFS ne sont décodées qu'autour des feux actifs. La grille\nmondiale aurait pesé plusieurs gigaoctets par cycle pour une information utile sur\nquelques dizaines de kilomètres carrés.",[138,530,531,534],{},[162,532,533],{},"Temps réel."," Server-Sent Events : pas de polling, pas de WebSocket bidirectionnel\nlà où un flux descendant suffit.",[138,536,537,540],{},[162,538,539],{},"Carto."," MapLibre GL, fond OpenFreeMap et vue satellite Esri — sans clé d'API, donc\nsans quota ni facturation surprise.",[133,542,347],{"id":346},[138,544,545],{},"Ajouter une zone de couverture, c'est une ligne de SQL. Cette contrainte de conception,\nposée tôt, a évité que la logique géographique se disperse dans le code applicatif.",{"title":71,"searchDepth":181,"depth":181,"links":547},[548,549,550,551],{"id":418,"depth":181,"text":419},{"id":428,"depth":181,"text":429},{"id":509,"depth":181,"text":510},{"id":346,"depth":181,"text":347},"Suivi des feux de forêt en temps réel à l'échelle mondiale, à partir de six sources satellitaires agrégées et affichées sur une carte vectorielle.",[554,555,556],"Six sources satellitaires agrégées, des orbites polaires aux géostationnaires","Estimation des zones brûlées calculée directement en PostGIS","Diffusion temps réel par Server-Sent Events, sans polling",{},"\u002Fprojets\u002Fpyro-radar",{"title":413,"description":552},"projets\u002Fpyro-radar",[16,20,28,35,34,562],"SSE","4ZCNz0DTUGNbGqICpRAmgsPoCLj_JIte-ATHfHBST_M",{"id":565,"title":566,"body":567,"cover":71,"demo":71,"description":643,"extension":187,"featured":117,"highlights":644,"meta":648,"navigation":123,"path":649,"rang":650,"repo":71,"role":651,"seo":652,"status":263,"stem":653,"tags":654,"type":56,"year":204,"__hash__":657},"projets\u002Fprojets\u002Frootine.md","Rootine",{"type":130,"value":568,"toc":637},[569,575,577,593,597,603,609,615,621,625,628,631,634],[570,571,572],"blockquote",{},[138,573,574],{},"Les habitudes sont les racines de qui tu deviens.",[133,576,136],{"id":135},[138,578,579,580,584,585,588,589,592],{},"Rootine — jeu de mots entre ",[581,582,583],"em",{},"root"," et ",[581,586,587],{},"routine"," — est une application de suivi\nd'habitudes construite autour d'un principe simple : ",[162,590,591],{},"la régularité bat l'intensité",".\nDix minutes de sport chaque jour valent mieux qu'une séance de deux heures par semaine.",[133,594,596],{"id":595},"fonctionnalités","Fonctionnalités",[138,598,599,602],{},[162,600,601],{},"Accueil"," — la checklist des habitudes du jour, avec case à cocher animée (ressort et\nretour haptique), barre de progression globale et message de félicitations quand tout est\nfait. Un bascule Hier \u002F Aujourd'hui permet de valider rétroactivement.",[138,604,605,608],{},[162,606,607],{},"Routines"," — création, modification et suppression des habitudes suivies.",[138,610,611,614],{},[162,612,613],{},"Calendrier"," — heatmap mensuelle, où l'intensité de la couleur reflète le taux de\ncomplétion du jour. La régularité devient visible d'un coup d'œil.",[138,616,617,620],{},[162,618,619],{},"Statistiques"," — séries en cours, taux de complétion, tendances dans le temps.",[133,622,624],{"id":623},"le-parti-pris","Le parti pris",[138,626,627],{},"La plupart des applications d'habitudes punissent l'oubli : séries cassées, badges perdus,\nnotifications culpabilisantes. Ce ressort motive une semaine puis produit l'effet inverse —\non désinstalle plutôt que d'affronter le tableau de bord.",[138,629,630],{},"Rootine assume l'inverse. On peut valider la veille, aucune série ne se casse\ndéfinitivement, et le ton reste encourageant. L'objectif est de tenir des mois, pas de\ngagner un score.",[133,632,223],{"id":633},"stack",[138,635,636],{},"SwiftUI et SwiftData, sans dépendance externe. Toutes les données restent sur l'appareil.",{"title":71,"searchDepth":181,"depth":181,"links":638},[639,640,641,642],{"id":135,"depth":181,"text":136},{"id":595,"depth":181,"text":596},{"id":623,"depth":181,"text":624},{"id":633,"depth":181,"text":223},"Application iOS de suivi d'habitudes, minimaliste et bienveillante — checklist du jour, calendrier heatmap et statistiques de régularité.",[645,646,647],"Validation rétroactive de la veille, sans culpabilisation","Calendrier heatmap mensuel et statistiques de tendance","Animations ressort et retour haptique sur chaque validation",{},"\u002Fprojets\u002Frootine",8,"Conception, design et développement iOS",{"title":566,"description":643},"projets\u002Frootine",[59,60,61,655,656],"Swift","Charts","5ebAW_I2ObF4-w_YsUQ8_pFxPmoLA4z2mfz_WqfbLDw",{"id":659,"title":660,"body":661,"cover":71,"demo":71,"description":698,"extension":187,"featured":117,"highlights":699,"meta":703,"navigation":123,"path":704,"rang":705,"repo":71,"role":651,"seo":706,"status":263,"stem":707,"tags":708,"type":56,"year":204,"__hash__":710},"projets\u002Fprojets\u002Fsofa.md","Sofa",{"type":130,"value":662,"toc":692},[663,665,668,670,677,680,684,687,689],[133,664,136],{"id":135},[138,666,667],{},"Sofa répond à un problème quotidien : savoir quoi regarder, et surtout se souvenir de ce\nqu'on voulait regarder. L'application permet de chercher un film ou une série via l'API\nTMDB, de l'ajouter à sa bibliothèque, de marquer ce qui a été vu, de noter les titres et\nde voir où les regarder en streaming.",[133,669,223],{"id":633},[138,671,672,673,676],{},"Application ",[162,674,675],{},"iOS 100 % native",", écrite en SwiftUI avec SwiftData pour la persistance.\nPas de framework multiplateforme, pas de WebView : les animations, les gestes et le\ncomportement du système sont ceux d'une application iOS, parce que c'est précisément ce\nqui distingue une application qu'on garde d'une application qu'on désinstalle.",[138,678,679],{},"SwiftData assure la persistance locale, ce qui rend la bibliothèque consultable hors\nconnexion — seules la recherche et la mise à jour des fiches nécessitent le réseau.",[133,681,683],{"id":682},"design","Design",[138,685,686],{},"Interface sombre, inspirée de l'ambiance d'une salle de cinéma : fonds profonds, affiches\nmises en valeur, typographie contrastée. Le design system est défini une fois — couleurs,\nespacements, typographies — puis appliqué de façon cohérente à tous les écrans.",[133,688,347],{"id":346},[138,690,691],{},"Venant du web, SwiftUI demande de désapprendre certains réflexes. Le système de layout ne\nfonctionne pas comme Flexbox, et la propagation d'état suit ses propres règles. En\nrevanche, l'intégration avec le système — widgets, partage, mode sombre, accessibilité —\nest sans commune mesure avec ce qu'on obtient dans une application web.",{"title":71,"searchDepth":181,"depth":181,"links":693},[694,695,696,697],{"id":135,"depth":181,"text":136},{"id":633,"depth":181,"text":223},{"id":682,"depth":181,"text":683},{"id":346,"depth":181,"text":347},"Application iOS native de watchlist films et séries — recherche via TMDB, bibliothèque personnelle, suivi des visionnages et notes.",[700,701,702],"Persistance locale avec SwiftData, utilisable hors connexion","Intégration TMDB — recherche, fiches détaillées et plateformes de streaming","Design system sombre inspiré des salles de cinéma",{},"\u002Fprojets\u002Fsofa",7,{"title":660,"description":698},"projets\u002Fsofa",[59,60,61,709,655],"TMDB API","ZzkgnJcV0g_FvZOo_GEoHRi0x3lwaCKhUM-FSnUQSTU",{"id":712,"title":713,"body":714,"cover":71,"demo":71,"description":828,"extension":187,"featured":117,"highlights":829,"meta":833,"navigation":123,"path":834,"rang":835,"repo":71,"role":836,"seo":837,"status":263,"stem":838,"tags":839,"type":844,"year":266,"__hash__":845},"projets\u002Fprojets\u002Fthanos.md","Thanos",{"type":130,"value":715,"toc":822},[716,718,721,725,779,782,786,812,816,819],[133,717,136],{"id":135},[138,719,720],{},"Thanos est un environnement complet pour prototyper, tester et comparer des stratégies de\ntrading à travers plusieurs exchanges et plusieurs unités de temps. L'objectif n'est pas\nde trader : c'est de disposer d'un banc d'essai honnête pour répondre à la question\n« est-ce que cette idée aurait fonctionné, et à quel prix en risque ».",[133,722,724],{"id":723},"stratégies-implémentées","Stratégies implémentées",[431,726,727,737],{},[434,728,729],{},[437,730,731,734],{},[440,732,733],{},"Stratégie",[440,735,736],{},"Principe",[450,738,739,747,755,763,771],{},[437,740,741,744],{},[455,742,743],{},"SMA",[455,745,746],{},"Croisement de moyennes mobiles simples",[437,748,749,752],{},[455,750,751],{},"EMA",[455,753,754],{},"Croisement de moyennes mobiles exponentielles",[437,756,757,760],{},[455,758,759],{},"Momentum (RSI)",[455,761,762],{},"Entrées sur zones de survente \u002F surachat",[437,764,765,768],{},[455,766,767],{},"SMA-EMA combiné",[455,769,770],{},"Confirmation croisée entre les deux familles de moyennes",[437,772,773,776],{},[455,774,775],{},"TRIX",[455,777,778],{},"Oscillateur de triple lissage exponentiel",[138,780,781],{},"Toutes partagent la même interface, ce qui permet de les évaluer sur un socle identique —\nmêmes données, mêmes frais, mêmes métriques.",[133,783,785],{"id":784},"modules","Modules",[293,787,788,794,800,806],{},[296,789,790,793],{},[162,791,792],{},"Data Manager"," — récupération et mise en cache des historiques par exchange et timeframe",[296,795,796,799],{},[162,797,798],{},"Custom Indicators"," — indicateurs techniques implémentés à la main plutôt qu'importés",[296,801,802,805],{},[162,803,804],{},"Backtest Analysis"," — métriques de performance et de risque",[296,807,808,811],{},[162,809,810],{},"Plot Analysis"," — visualisation des entrées, sorties et courbes de capital",[133,813,815],{"id":814},"le-vrai-enseignement","Le vrai enseignement",[138,817,818],{},"La difficulté d'un backtest n'est pas de le faire fonctionner : c'est de l'empêcher de\nmentir. Les biais s'y glissent facilement — utiliser une donnée qui n'était pas encore\ndisponible au moment de la décision, ignorer les frais et le slippage, ou optimiser les\nparamètres sur la même période que celle qui sert à valider la stratégie.",[138,820,821],{},"Une stratégie qui affiche un résultat spectaculaire en backtest est presque toujours le\nsigne d'une fuite de données quelque part, pas d'une découverte.",{"title":71,"searchDepth":181,"depth":181,"links":823},[824,825,826,827],{"id":135,"depth":181,"text":136},{"id":723,"depth":181,"text":724},{"id":784,"depth":181,"text":785},{"id":814,"depth":181,"text":815},"Plateforme de recherche, de backtesting et d'analyse de stratégies de trading sur les marchés de crypto-monnaies.",[830,831,832],"Cinq familles de stratégies comparables sur un même socle de test","Indicateurs techniques personnalisés implémentés à la main","Gestion du cache de données historiques multi-exchanges et multi-timeframes",{},"\u002Fprojets\u002Fthanos",6,"Conception et développement",{"title":713,"description":828},"projets\u002Fthanos",[25,840,841,842,843],"Pandas","NumPy","Backtesting","Data analysis","Data","e8XGUjU3vl1_ZCB24j4UepMSSypU9b5MDY8iMrxu8jM",{"id":847,"title":848,"body":849,"cover":71,"demo":71,"description":1036,"extension":187,"featured":123,"highlights":1037,"meta":1042,"navigation":123,"path":1043,"rang":1044,"repo":71,"role":195,"seo":1045,"status":197,"stem":1046,"tags":1047,"type":203,"year":372,"__hash__":1048},"projets\u002Fprojets\u002Fvigie.md","Vigie",{"type":130,"value":850,"toc":1028},[851,853,856,859,863,895,898,900,949,969,973,976,990,994,1001,1019,1021],[133,852,276],{"id":275},[138,854,855],{},"J'avais une dizaine de projets en ligne et aucune vision d'ensemble : est-ce que le\ncron de la nuit est passé ? Est-ce que l'API répond encore ? Combien de visiteurs\ncette semaine ? Chaque réponse demandait de se connecter à un serveur différent.",[138,857,858],{},"Brancher un service tiers par projet aurait multiplié les comptes, les coûts et les\nbandeaux de cookies. J'ai préféré construire l'outil unique qui me manquait.",[133,860,862],{"id":861},"ce-que-fait-vigie","Ce que fait Vigie",[293,864,865,871,877,883,889],{},[296,866,867,870],{},[162,868,869],{},"Analytique de visite"," sans cookie ni identifiant persistant — aucun bandeau de consentement nécessaire",[296,872,873,876],{},[162,874,875],{},"Surveillance de disponibilité"," : sondes HTTP régulières avec historique et calcul d'uptime",[296,878,879,882],{},[162,880,881],{},"Supervision des tâches planifiées"," : un cron qui ne s'est pas signalé dans sa fenêtre déclenche une alerte",[296,884,885,888],{},[162,886,887],{},"Suivi des erreurs"," applicatives remontées par les projets branchés",[296,890,891,894],{},[162,892,893],{},"Page de statut publique",", alimentée par les mêmes données que le tableau de bord interne",[138,896,897],{},"Chaque projet supervisé possède sa clé API, et ne voit jamais les données des autres.",[133,899,147],{"id":146},[431,901,902,912],{},[434,903,904],{},[437,905,906,909],{},[440,907,908],{},"Couche",[440,910,911],{},"Choix",[450,913,914,922,930,938],{},[437,915,916,919],{},[455,917,918],{},"API",[455,920,921],{},"AdonisJS v6, TypeScript, Lucid",[437,923,924,927],{},[455,925,926],{},"Base",[455,928,929],{},"PostgreSQL 17",[437,931,932,935],{},[455,933,934],{},"Interface",[455,936,937],{},"Vue 3, Vite, Pinia, TypeScript",[437,939,940,943],{},[455,941,942],{},"Déploiement",[455,944,945,946],{},"Docker Compose sur VPS, Caddy en frontal, GitHub Actions sur ",[156,947,948],{},"main",[138,950,951,952,955,956,955,959,955,962,955,965,968],{},"Tout tourne en conteneurs — ",[156,953,954],{},"postgres",", ",[156,957,958],{},"redis",[156,960,961],{},"api",[156,963,964],{},"worker",[156,966,967],{},"web"," — sans aucun\nNode requis sur la machine hôte. Le worker traite les sondes et les agrégations hors\ndu cycle de requête, ce qui garde l'API réactive quel que soit le nombre de projets\nsupervisés.",[133,970,972],{"id":971},"le-greffon-côté-client","Le greffon côté client",[138,974,975],{},"Collecter suppose de poser du code dans la page des autres : un bug ici ne dégrade\npas Vigie, il dégrade le site supervisé. Le script tient donc sous deux kilo-octets,\nsans cookie ni empreinte de navigateur — et le budget est vérifié à la compilation,\nla construction échoue plutôt que de livrer plus lourd.",[138,977,978,979,584,982,985,986,989],{},"Il enveloppe ",[156,980,981],{},"pushState",[156,983,984],{},"replaceState"," pour détecter les navigations d'une\napplication monopage, puis restaure les méthodes d'origine : rien n'est altéré\ndurablement pour l'application hôte. Un greffon ",[156,987,988],{},"@vigie\u002Fjs"," se branche directement\nsur le routeur Vue 3, plutôt que de deviner depuis l'historique.",[133,991,993],{"id":992},"un-serveur-mcp-pour-ne-pas-quitter-léditeur","Un serveur MCP, pour ne pas quitter l'éditeur",[138,995,996,997,1000],{},"Qu'est-ce qui est cassé ? Cette erreur est-elle nouvelle ? Le cron de la nuit est-il\npassé ? Vigie expose six outils de lecture en ",[162,998,999],{},"MCP",", pour répondre à ces questions\nsans ouvrir le tableau de bord.",[138,1002,1003,1004,1007,1008,955,1011,1014,1015,1018],{},"Deux partis pris : ",[162,1005,1006],{},"aucune écriture"," — un assistant qui lit se trompe de\ndiagnostic, un assistant qui écrit se trompe de production ; et ",[162,1009,1010],{},"les codes internes\ntraduits avant de sortir",[156,1012,1013],{},"cause: \"agent muet\""," plutôt que ",[156,1016,1017],{},"reason: 5",", parce qu'un\nmodèle face à un code inconnu ne s'arrête pas, il devine.",[133,1020,347],{"id":346},[138,1022,1023,1024,1027],{},"Le point dur n'était pas la collecte mais la ",[162,1025,1026],{},"rétention"," : conserver des années de\npoints de mesure sans faire exploser la base. La réponse a été l'agrégation\nprogressive — les données fines vieillissent en moyennes horaires, puis journalières.",{"title":71,"searchDepth":181,"depth":181,"links":1029},[1030,1031,1032,1033,1034,1035],{"id":275,"depth":181,"text":276},{"id":861,"depth":181,"text":862},{"id":146,"depth":181,"text":147},{"id":971,"depth":181,"text":972},{"id":992,"depth":181,"text":993},{"id":346,"depth":181,"text":347},"Supervision unifiée de mes projets web — analytique sans cookies, monitoring de disponibilité, suivi des tâches planifiées et page de statut publique.",[1038,1039,1040,1041],"Multi-projets avec isolation stricte des données par clé API","Analytique de visite sans cookie, donc sans bandeau de consentement","Alertes et page de statut publique générée automatiquement","Serveur MCP en lecture seule — la supervision interrogeable depuis l'éditeur",{},"\u002Fprojets\u002Fvigie",1,{"title":848,"description":1036},"projets\u002Fvigie",[28,16,18,34,37,51,999],"LTU-3C4s228_PQtE_ZPc12A95pk0zt4X3GWFfXalLOs",{"left":115,"top":115,"width":116,"height":116,"rotate":115,"vFlip":117,"hFlip":117,"body":1050},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",{"left":115,"top":115,"width":116,"height":116,"rotate":115,"vFlip":117,"hFlip":117,"body":1052},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M20 6L9 17l-5-5\"\u002F>",{"left":115,"top":115,"width":116,"height":116,"rotate":115,"vFlip":117,"hFlip":117,"body":1054},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 12h14m-7-7l7 7l-7 7\"\u002F>",1787092923198]